Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ export default antfu(
{
type: 'lib',
},
{
rules: {
'unused-imports/no-unused-vars': 'warn',

},
},
)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"packageManager": "pnpm@10.4.0",
"scripts": {
"build": "nr -r build",
"dev": "nr -r dev",
"dev": "nr --parallel dev",
"lint": "eslint --cache .",
"prepublishOnly": "nr build",
"docs": "pnpm -C docs run docs:dev",
Expand Down
3 changes: 3 additions & 0 deletions packages/layout/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig.json"
}
3 changes: 3 additions & 0 deletions packages/math/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `@sciux/math`

Mathematics components for SciuxKit
39 changes: 39 additions & 0 deletions packages/math/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "@sciux/math",
"type": "module",
"version": "0.0.5",
"description": "Layout components for SciuxKit",
"author": "BijonAI <info@bijon.ai>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/sciux-kit/lib.git"
},
"bugs": "https://github.com/sciux-kit/lib/issues",
"keywords": [],
"exports": {
".": {
"types": "./src/index.ts",
"import": "./dist/index.js"
}
},
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"files": [
"dist"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"prepublishOnly": "nr build",
"start": "tsx src/index.ts"
},
"dependencies": {
"@sciux/utils-theme": "workspace:^",
"@sciux/widget": "workspace:^",
"@vue/reactivity": "^3.5.14",
"arktype": "^2.1.20",
"sciux-laplace": "catalog:"
}
}
49 changes: 49 additions & 0 deletions packages/math/src/angle/arc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { theme } from '@sciux/utils-theme'
import { type } from 'arktype'
import { defineComponent } from 'sciux-laplace'
import { LineType } from '../shared'
import { describeArc } from '../utils/arc-path'
import { resolveDasharray } from '../utils/line'
import { generateTexNode } from '../utils/tex'

const T = type({
type: LineType,
value: type.string,
})

export const arc = defineComponent<'arc', typeof T.infer, {
x: number
y: number
from: number
to: number
startSide: number
endSide: number
}>((attrs, context) => {
return {
name: 'arc',
attrs: T,
defaults: {
value: '',
},
setup() {
const container = document.createElementNS('http://www.w3.org/2000/svg', 'g')
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
path.setAttribute('d', describeArc([context.x, context.y], (context.startSide ?? context.endSide) / 3, context.from, context.to))
path.setAttribute('stroke', theme.pallete('primary'))
path.setAttribute('fill', 'none')
path.setAttribute('stroke-dasharray', resolveDasharray(attrs.type.value))
const texElement = generateTexNode(attrs.value?.value)
const length = (context.startSide ?? context.endSide) / 3
const angle = context.from + (context.to - context.from) / 2
const position = [
length * Math.cos(angle * Math.PI / 180),
length * Math.sin(angle * Math.PI / 180),
]
const texContainer = document.createElementNS('http://www.w3.org/2000/svg', 'g')
texContainer.setAttribute('transform', `translate(${position[0]}, ${position[1]})`)
texContainer.append(texElement)
container.append(path, texContainer)
return container
},
}
})
52 changes: 52 additions & 0 deletions packages/math/src/angle/bouding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { theme } from '@sciux/utils-theme'
import { type } from 'arktype'
import { defineComponent } from 'sciux-laplace'
import { LineType } from '../shared'
import { describeArc } from '../utils/arc-path'
import { resolveDasharray } from '../utils/line'
import { generateTexNode } from '../utils/tex'

const T = type({
type: LineType,
value: type.string,
})

export const bounding = defineComponent<'bounding', typeof T.infer, {
x: number
y: number
from: number
to: number
startSide?: number
endSide: number
}>((attrs, context) => {
return {
name: 'bounding',
attrs: T,
defaults: {
type: 'solid',
value: '',
},
setup() {
const container = document.createElementNS('http://www.w3.org/2000/svg', 'g')
const pathString = describeArc([context.x, context.y], context.startSide ?? context.endSide, context.from, context.to)
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
path.setAttribute('d', pathString)
path.setAttribute('stroke-width', '1')
path.setAttribute('stroke', theme.pallete('primary'))
path.setAttribute('fill', 'none')
path.setAttribute('stroke-dasharray', resolveDasharray(attrs.type.value))
const texElement = generateTexNode(attrs.value?.value)
const length = context.startSide ?? context.endSide
const angle = context.from + (context.to - context.from) / 2
const position = [
length * Math.cos(angle * Math.PI / 180),
length * Math.sin(angle * Math.PI / 180),
]
const texContainer = document.createElementNS('http://www.w3.org/2000/svg', 'g')
texContainer.setAttribute('transform', `translate(${position[0]}, ${position[1]})`)
texContainer.append(texElement)
container.append(path, texContainer)
return container
},
}
})
84 changes: 84 additions & 0 deletions packages/math/src/angle/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { theme } from '@sciux/utils-theme'
import { type } from 'arktype'
import { defineComponent } from 'sciux-laplace'
import { LineType } from '../shared'
import { resolveDasharray } from '../utils/line'
import { arc } from './arc'
import { bounding } from './bouding'
import { angleEndPoint, angleStartPoint, origin } from './points'

const T = type({
x: 'number',
y: 'number',
from: 'number',
to: 'number',
startSide: 'number',
endSide: 'number',
startSideType: LineType,
endSideType: LineType,
startSideValue: type.string.optional(),
endSideValue: type.string.optional(),
})

export const angle = defineComponent<'angle', typeof T.infer>((attrs) => {
const space = new Map()
space.set('arc', arc)
space.set('bounding', bounding)
space.set('start-point', angleStartPoint)
space.set('end-point', angleEndPoint)
space.set('origin', origin)
return {
name: 'angle',
attrs: T,
defaults: {
startSide: 10,
endSide: 10,
startSideType: 'solid',
endSideType: 'solid',
},
setup(children) {
const container = document.createElementNS('http://www.w3.org/2000/svg', 'g')
container.setAttribute('transform', `translate(${attrs.x.value}, ${attrs.y.value})`)
const resolve = (value: number, length: number): { x1: number, y1: number, x2: number, y2: number } => {
const radian = value * Math.PI / 180
return {
x1: 0,
y1: 0,
x2: length * Math.cos(radian),
y2: length * Math.sin(radian),
}
}
const startSide = resolve(attrs.from.value, attrs.startSide.value)
const endSide = resolve(attrs.to.value, attrs.endSide.value)
const startSideLine = document.createElementNS('http://www.w3.org/2000/svg', 'line')
startSideLine.setAttribute('x1', startSide.x1.toString())
startSideLine.setAttribute('y1', startSide.y1.toString())
startSideLine.setAttribute('x2', startSide.x2.toString())
startSideLine.setAttribute('y2', startSide.y2.toString())
startSideLine.setAttribute('stroke', theme.pallete('primary'))
startSideLine.setAttribute('stroke-width', '1')
startSideLine.setAttribute('stroke-dasharray', resolveDasharray(attrs.startSideType.value))
container.append(startSideLine)
const endSideLine = document.createElementNS('http://www.w3.org/2000/svg', 'line')
endSideLine.setAttribute('x1', endSide.x1.toString())
endSideLine.setAttribute('y1', endSide.y1.toString())
endSideLine.setAttribute('x2', endSide.x2.toString())
endSideLine.setAttribute('y2', endSide.y2.toString())
endSideLine.setAttribute('stroke', theme.pallete('primary'))
endSideLine.setAttribute('stroke-width', '1')
endSideLine.setAttribute('stroke-dasharray', resolveDasharray(attrs.endSideType.value))
container.append(endSideLine)
container.append(...children())
return container
},
provides: {
x: attrs.x,
y: attrs.y,
from: attrs.from,
to: attrs.to,
startSide: attrs.startSide,
endSide: attrs.endSide,
},
space,
}
})
51 changes: 51 additions & 0 deletions packages/math/src/angle/points.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { defineComponent } from 'sciux-laplace'
import { InfoPointType } from '../shared'

export const angleStartPoint = defineComponent<'start-point', typeof InfoPointType.infer, {
x: number
y: number
startSide: number
from: number
}>((attrs, context) => {
return {
name: 'start-point',
attrs: InfoPointType,
globals: {
[attrs.as.value]: [
context.startSide * Math.cos(context.from * Math.PI / 180),
context.startSide * Math.sin(context.from * Math.PI / 180),
],
},
}
})

export const angleEndPoint = defineComponent<'end-point', typeof InfoPointType.infer, {
x: number
y: number
endSide: number
to: number
}>((attrs, context) => {
return {
name: 'end-point',
attrs: InfoPointType,
globals: {
[attrs.as.value]: [
context.endSide * Math.cos(context.to * Math.PI / 180),
context.endSide * Math.sin(context.to * Math.PI / 180),
],
},
}
})

export const origin = defineComponent<'origin', typeof InfoPointType.infer, {
x: number
y: number
}>((attrs, context) => {
return {
name: 'origin',
attrs: InfoPointType,
globals: {
[attrs.as.value]: [context.x, context.y],
},
}
})
79 changes: 79 additions & 0 deletions packages/math/src/axis/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { theme } from '@sciux/utils-theme'
import { type } from 'arktype'
import { defineComponent } from 'sciux-laplace'

const T = type({

Check warning on line 5 in packages/math/src/axis/index.ts

View workflow job for this annotation

GitHub Actions / lint

'T' is assigned a value but only used as a type. Allowed unused vars must match /^_/u
x: type.number,
y: type.number,
division: type.number,
range: type('number[]'),
label: type.unknown,
direction: type.enumerated('top', 'bottom', 'left', 'right'),
})
interface withLabelT {
label: (count: number) => string
}

export const resolveDirection = (value: string): 1 | -1 => ['left', 'top'].includes(value) ? -1 : 1

export const axis = defineComponent<'axis', typeof T.infer & withLabelT>((attrs) => {

Check failure on line 19 in packages/math/src/axis/index.ts

View workflow job for this annotation

GitHub Actions / lint

Type '{ x: number; y: number; division: number; range: number[]; label: unknown; direction: "top" | "left" | "right" | "bottom"; } & withLabelT' does not satisfy the constraint 'Record<string, unknown>'.
return {
name: 'axis',
provides: {
division: attrs.division,
},
defaults: {
division: 20,
label: (count: number) => count.toString(),
direction: 'right',
},
setup(children) {
const root = document.createElementNS('http://www.w3.org/2000/svg', 'g')
root.setAttribute('transform', `translate(${attrs.x.value}, ${attrs.y.value})`)
const axes = document.createElementNS('http://www.w3.org/2000/svg', 'g')
// axis line
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line')
line.setAttribute(['left', 'right'].includes(attrs.direction.value) ? 'x1' : 'y1', (attrs.range.value[0] * attrs.division.value * resolveDirection(attrs.direction.value)).toString())
line.setAttribute(['left', 'right'].includes(attrs.direction.value) ? 'x2' : 'y2', (attrs.range.value[1] * attrs.division.value * resolveDirection(attrs.direction.value)).toString())
axes.append(line)
// axis arrow
const arrow = document.createElementNS('http://www.w3.org/2000/svg', 'polygon')
arrow.setAttribute('points', '0,0 -7,5 10,0 -7,-5 0,0')
arrow.setAttribute('transform', `translate(${['left', 'right'].includes(attrs.direction.value) ? '' : '0,'} ${attrs.range.value[1] * attrs.division.value * resolveDirection(attrs.direction.value)}${['top', 'bottom'].includes(attrs.direction.value) ? '' : ' ,0'})
rotate(${attrs.direction.value === 'left' ? '180' : attrs.direction.value === 'top' ? '270' : attrs.direction.value === 'bottom' ? '90' : '0'})`)
axes.append(arrow)
// axis ticks
const ticks = document.createElementNS('http://www.w3.org/2000/svg', 'g')
for (let i = attrs.range.value[0]; i < attrs.range.value[1]; i += 1) {
const tick = document.createElementNS('http://www.w3.org/2000/svg', 'line')
tick.setAttribute(['left', 'right'].includes(attrs.direction.value) ? 'x1' : 'y1', (i * attrs.division.value * resolveDirection(attrs.direction.value)).toString())
tick.setAttribute(['left', 'right'].includes(attrs.direction.value) ? 'x2' : 'y2', (i * attrs.division.value * resolveDirection(attrs.direction.value)).toString())
tick.setAttribute(['left', 'right'].includes(attrs.direction.value) ? 'y1' : 'x1', '-2')
tick.setAttribute(['left', 'right'].includes(attrs.direction.value) ? 'y2' : 'x2', '2')
ticks.append(tick)
}
axes.append(ticks)
// axis labels
const labels = document.createElementNS('http://www.w3.org/2000/svg', 'g')
labels.setAttribute('stroke', 'none')
labels.setAttribute('text-anchor', 'middle')
labels.setAttribute('dominant-baseline', 'middle')
labels.setAttribute('font-size', theme.size('3xs'))
labels.style.fontFamily = theme.font('math')
for (let i = attrs.range.value[0]; i < attrs.range.value[1]; i += 1) {
const label = document.createElementNS('http://www.w3.org/2000/svg', 'text')
label.setAttribute(['left', 'right'].includes(attrs.direction.value) ? 'x' : 'y', (i * attrs.division.value * resolveDirection(attrs.direction.value)).toString())
label.setAttribute(['left', 'right'].includes(attrs.direction.value) ? 'y' : 'x', '16')
label.textContent = attrs.label.value(i)
labels.append(label)
}
axes.append(labels)

axes.setAttribute('fill', theme.pallete('primary'))
axes.setAttribute('stroke', theme.pallete('primary'))
root.append(axes, ...children())

return root
},
}
})
Loading
Loading