@prestack/thread-ui 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/dist/ui/animations/anm_appear.ts +13 -0
  2. package/dist/ui/animations/anm_blur_in.ts +19 -0
  3. package/dist/ui/animations/anm_blur_out.ts +18 -0
  4. package/dist/ui/animations/anm_dismiss.ts +18 -0
  5. package/dist/ui/animations/anm_drop.ts +19 -0
  6. package/dist/ui/animations/anm_fall.ts +18 -0
  7. package/dist/ui/animations/anm_flash.ts +18 -0
  8. package/dist/ui/animations/anm_glow.ts +16 -0
  9. package/dist/ui/animations/anm_lift.ts +16 -0
  10. package/dist/ui/animations/anm_nudge.ts +16 -0
  11. package/dist/ui/animations/anm_pop_in.ts +23 -0
  12. package/dist/ui/animations/anm_pop_out.ts +22 -0
  13. package/dist/ui/animations/anm_press.ts +12 -0
  14. package/dist/ui/animations/anm_pulse.ts +13 -0
  15. package/dist/ui/animations/anm_rise.ts +19 -0
  16. package/dist/ui/animations/anm_shake.ts +13 -0
  17. package/dist/ui/animations/anm_slide_in_left.ts +19 -0
  18. package/dist/ui/animations/anm_slide_in_right.ts +19 -0
  19. package/dist/ui/animations/anm_slide_out_left.ts +18 -0
  20. package/dist/ui/animations/anm_slide_out_right.ts +18 -0
  21. package/dist/ui/animations/anm_spin.ts +12 -0
  22. package/dist/ui/animations/anm_swell.ts +16 -0
  23. package/dist/ui/animations/anm_wobble.ts +24 -0
  24. package/dist/ui/animations/anm_zoom_in.ts +19 -0
  25. package/dist/ui/animations/anm_zoom_out.ts +18 -0
  26. package/dist/ui/animations.ts +317 -0
  27. package/dist/ui/attach.js +13 -4
  28. package/dist/ui/attach.ts +613 -0
  29. package/dist/ui/charts.tsx +74 -0
  30. package/dist/ui/checked.d.ts +2 -2
  31. package/dist/ui/checked.ts +32 -0
  32. package/dist/ui/collector.ts +140 -0
  33. package/dist/ui/compositions.d.ts +10 -1
  34. package/dist/ui/compositions.js +262 -23
  35. package/dist/ui/compositions.ts +640 -0
  36. package/dist/ui/consent.ts +55 -0
  37. package/dist/ui/content.tsx +39 -0
  38. package/dist/ui/contrast.ts +27 -0
  39. package/dist/ui/controls.tsx +30 -0
  40. package/dist/ui/disclosure.tsx +22 -0
  41. package/dist/ui/dismiss-layer.ts +87 -0
  42. package/dist/ui/door.ts +140 -0
  43. package/dist/ui/drag.ts +316 -0
  44. package/dist/ui/elements/accordion.js +2 -2
  45. package/dist/ui/elements/accordion.tsx +47 -0
  46. package/dist/ui/elements/accordion.works.ts +66 -0
  47. package/dist/ui/elements/aspect-ratio.js +1 -1
  48. package/dist/ui/elements/aspect-ratio.tsx +30 -0
  49. package/dist/ui/elements/aspect-ratio.works.ts +5 -0
  50. package/dist/ui/elements/avatar.js +1 -1
  51. package/dist/ui/elements/avatar.tsx +33 -0
  52. package/dist/ui/elements/avatar.works.ts +16 -0
  53. package/dist/ui/elements/badge.js +1 -1
  54. package/dist/ui/elements/badge.tsx +32 -0
  55. package/dist/ui/elements/badge.works.ts +9 -0
  56. package/dist/ui/elements/bars.js +2 -2
  57. package/dist/ui/elements/bars.tsx +49 -0
  58. package/dist/ui/elements/bars.works.ts +29 -0
  59. package/dist/ui/elements/box.js +3 -2
  60. package/dist/ui/elements/box.tsx +35 -0
  61. package/dist/ui/elements/breadcrumb.js +2 -2
  62. package/dist/ui/elements/breadcrumb.tsx +37 -0
  63. package/dist/ui/elements/breadcrumb.works.ts +24 -0
  64. package/dist/ui/elements/button.js +1 -1
  65. package/dist/ui/elements/button.tsx +45 -0
  66. package/dist/ui/elements/button.works.tsx +52 -0
  67. package/dist/ui/elements/column.js +1 -1
  68. package/dist/ui/elements/column.tsx +28 -0
  69. package/dist/ui/elements/consent.js +2 -2
  70. package/dist/ui/elements/consent.tsx +70 -0
  71. package/dist/ui/elements/consent.works.tsx +132 -0
  72. package/dist/ui/elements/donut.js +2 -2
  73. package/dist/ui/elements/donut.tsx +44 -0
  74. package/dist/ui/elements/donut.works.ts +42 -0
  75. package/dist/ui/elements/each.js +1 -1
  76. package/dist/ui/elements/each.tsx +33 -0
  77. package/dist/ui/elements/each.works.tsx +82 -0
  78. package/dist/ui/elements/empty.js +1 -1
  79. package/dist/ui/elements/empty.tsx +32 -0
  80. package/dist/ui/elements/field.js +1 -1
  81. package/dist/ui/elements/field.tsx +44 -0
  82. package/dist/ui/elements/field.works.ts +65 -0
  83. package/dist/ui/elements/funnel.js +2 -2
  84. package/dist/ui/elements/funnel.tsx +49 -0
  85. package/dist/ui/elements/funnel.works.ts +37 -0
  86. package/dist/ui/elements/gauge.js +1 -1
  87. package/dist/ui/elements/gauge.tsx +39 -0
  88. package/dist/ui/elements/gauge.works.ts +42 -0
  89. package/dist/ui/elements/glyph.js +1 -1
  90. package/dist/ui/elements/glyph.tsx +29 -0
  91. package/dist/ui/elements/glyph.works.tsx +42 -0
  92. package/dist/ui/elements/grid.js +1 -1
  93. package/dist/ui/elements/grid.tsx +28 -0
  94. package/dist/ui/elements/heatmap.js +2 -2
  95. package/dist/ui/elements/heatmap.tsx +47 -0
  96. package/dist/ui/elements/heatmap.works.ts +24 -0
  97. package/dist/ui/elements/hit-box.js +1 -1
  98. package/dist/ui/elements/hit-box.tsx +46 -0
  99. package/dist/ui/elements/hit-box.works.tsx +576 -0
  100. package/dist/ui/elements/image.js +1 -1
  101. package/dist/ui/elements/image.tsx +28 -0
  102. package/dist/ui/elements/line-chart.js +2 -2
  103. package/dist/ui/elements/line-chart.tsx +44 -0
  104. package/dist/ui/elements/line-chart.works.ts +41 -0
  105. package/dist/ui/elements/link.js +1 -1
  106. package/dist/ui/elements/link.tsx +37 -0
  107. package/dist/ui/elements/link.works.ts +25 -0
  108. package/dist/ui/elements/media.js +1 -1
  109. package/dist/ui/elements/media.tsx +56 -0
  110. package/dist/ui/elements/menu.js +2 -2
  111. package/dist/ui/elements/menu.tsx +50 -0
  112. package/dist/ui/elements/menu.works.tsx +153 -0
  113. package/dist/ui/elements/money.js +1 -1
  114. package/dist/ui/elements/money.tsx +28 -0
  115. package/dist/ui/elements/money.works.ts +9 -0
  116. package/dist/ui/elements/pagination.js +2 -2
  117. package/dist/ui/elements/pagination.tsx +38 -0
  118. package/dist/ui/elements/pagination.works.ts +20 -0
  119. package/dist/ui/elements/progress.js +1 -1
  120. package/dist/ui/elements/progress.tsx +33 -0
  121. package/dist/ui/elements/progress.works.ts +8 -0
  122. package/dist/ui/elements/radio-group.js +2 -2
  123. package/dist/ui/elements/radio-group.tsx +49 -0
  124. package/dist/ui/elements/radio-group.works.ts +33 -0
  125. package/dist/ui/elements/row.js +1 -1
  126. package/dist/ui/elements/row.tsx +28 -0
  127. package/dist/ui/elements/scatter.js +1 -1
  128. package/dist/ui/elements/scatter.tsx +41 -0
  129. package/dist/ui/elements/scatter.works.ts +38 -0
  130. package/dist/ui/elements/select.js +2 -2
  131. package/dist/ui/elements/select.tsx +42 -0
  132. package/dist/ui/elements/select.works.ts +5 -0
  133. package/dist/ui/elements/separator.js +1 -1
  134. package/dist/ui/elements/separator.tsx +30 -0
  135. package/dist/ui/elements/skeleton.js +1 -1
  136. package/dist/ui/elements/skeleton.tsx +30 -0
  137. package/dist/ui/elements/slider.js +1 -1
  138. package/dist/ui/elements/slider.tsx +33 -0
  139. package/dist/ui/elements/slider.works.ts +5 -0
  140. package/dist/ui/elements/sparkline.js +1 -1
  141. package/dist/ui/elements/sparkline.tsx +36 -0
  142. package/dist/ui/elements/sparkline.works.ts +32 -0
  143. package/dist/ui/elements/spinner.js +1 -1
  144. package/dist/ui/elements/spinner.tsx +32 -0
  145. package/dist/ui/elements/stack.js +1 -1
  146. package/dist/ui/elements/stack.tsx +28 -0
  147. package/dist/ui/elements/stat.js +1 -1
  148. package/dist/ui/elements/stat.tsx +35 -0
  149. package/dist/ui/elements/stat.works.ts +14 -0
  150. package/dist/ui/elements/surface.js +1 -1
  151. package/dist/ui/elements/surface.tsx +35 -0
  152. package/dist/ui/elements/surface.works.ts +9 -0
  153. package/dist/ui/elements/table.js +2 -2
  154. package/dist/ui/elements/table.tsx +61 -0
  155. package/dist/ui/elements/table.works.ts +30 -0
  156. package/dist/ui/elements/tabs.js +2 -2
  157. package/dist/ui/elements/tabs.tsx +47 -0
  158. package/dist/ui/elements/tabs.works.ts +84 -0
  159. package/dist/ui/elements/text.js +1 -1
  160. package/dist/ui/elements/text.tsx +32 -0
  161. package/dist/ui/elements/textarea.js +1 -1
  162. package/dist/ui/elements/textarea.tsx +37 -0
  163. package/dist/ui/elements/textarea.works.ts +5 -0
  164. package/dist/ui/elements/time.js +1 -1
  165. package/dist/ui/elements/time.tsx +34 -0
  166. package/dist/ui/elements/time.works.ts +25 -0
  167. package/dist/ui/elements/toggle.js +1 -1
  168. package/dist/ui/elements/toggle.tsx +33 -0
  169. package/dist/ui/elements/toggle.works.ts +5 -0
  170. package/dist/ui/elements/tooltip.js +1 -1
  171. package/dist/ui/elements/tooltip.tsx +39 -0
  172. package/dist/ui/elements/tooltip.works.ts +77 -0
  173. package/dist/ui/elements/value.js +1 -1
  174. package/dist/ui/elements/value.tsx +30 -0
  175. package/dist/ui/elements/value.works.ts +9 -0
  176. package/dist/ui/elements.ts +127 -0
  177. package/dist/ui/focus-scope.ts +121 -0
  178. package/dist/ui/fonts.ts +355 -0
  179. package/dist/ui/generators/dev.ts +79 -0
  180. package/dist/ui/generators/elements.d.ts +1 -11
  181. package/dist/ui/generators/elements.js +43 -13
  182. package/dist/ui/generators/elements.ts +794 -0
  183. package/dist/ui/generators/i18n.ts +301 -0
  184. package/dist/ui/generators/icons.ts +214 -0
  185. package/dist/ui/generators/react.js +10 -3
  186. package/dist/ui/generators/react.ts +268 -0
  187. package/dist/ui/generators/routes.d.ts +1 -0
  188. package/dist/ui/generators/routes.js +89 -69
  189. package/dist/ui/generators/routes.ts +739 -0
  190. package/dist/ui/generators/show.ts +259 -0
  191. package/dist/ui/generators/styles.js +1 -1
  192. package/dist/ui/generators/styles.ts +670 -0
  193. package/dist/ui/generators/variants.ts +205 -0
  194. package/dist/ui/i18n/catalogs/en.ts +191 -0
  195. package/dist/ui/i18n/format.ts +221 -0
  196. package/dist/ui/i18n/locales.ts +33 -0
  197. package/dist/ui/i18n/parse.ts +315 -0
  198. package/dist/ui/i18n/translator.ts +31 -0
  199. package/dist/ui/i18n/types.ts +96 -0
  200. package/dist/ui/icons.ts +331 -0
  201. package/dist/ui/islands/map.ts +58 -0
  202. package/dist/ui/localizations.ts +75 -0
  203. package/dist/ui/makers/message.ts +292 -0
  204. package/dist/ui/material.ts +236 -0
  205. package/dist/ui/materials/mat_bordered.ts +13 -0
  206. package/dist/ui/materials/mat_ceramic.ts +13 -0
  207. package/dist/ui/materials/mat_clay.ts +13 -0
  208. package/dist/ui/materials/mat_elevated.ts +24 -0
  209. package/dist/ui/materials/mat_flat.ts +34 -0
  210. package/dist/ui/materials/mat_glass.ts +20 -0
  211. package/dist/ui/materials/mat_lit.ts +13 -0
  212. package/dist/ui/materials/mat_moulded.ts +11 -0
  213. package/dist/ui/materials.ts +206 -0
  214. package/dist/ui/modes.ts +44 -0
  215. package/dist/ui/navigation.tsx +32 -0
  216. package/dist/ui/positioning.ts +90 -0
  217. package/dist/ui/presented.tsx +119 -0
  218. package/dist/ui/provider.d.ts +2 -0
  219. package/dist/ui/provider.js +7 -1
  220. package/dist/ui/provider.tsx +182 -0
  221. package/dist/ui/render-loop.ts +133 -0
  222. package/dist/ui/roving-focus.ts +161 -0
  223. package/dist/ui/screens.js +17 -8
  224. package/dist/ui/screens.ts +142 -0
  225. package/dist/ui/scroll-lock.ts +28 -0
  226. package/dist/ui/series.ts +97 -0
  227. package/dist/ui/signals.ts +386 -0
  228. package/dist/ui/styleguide.ts +231 -0
  229. package/dist/ui/styleguides.ts +374 -0
  230. package/dist/ui/themes.ts +22 -0
  231. package/dist/ui/token.js +1 -1
  232. package/dist/ui/token.ts +78 -0
  233. package/dist/ui/tokens/shadow.ts +25 -0
  234. package/dist/ui/tokens.ts +235 -0
  235. package/dist/ui/validators.ts +232 -0
  236. package/dist/ui/variant.d.ts +1 -0
  237. package/dist/ui/variant.js +3 -0
  238. package/dist/ui/variant.ts +352 -0
  239. package/dist/ui/variants/var_avatar-round.ts +14 -0
  240. package/dist/ui/variants/var_bubble-me.ts +14 -0
  241. package/dist/ui/variants/var_bubble-them.ts +13 -0
  242. package/dist/ui/variants/var_button-border.ts +76 -0
  243. package/dist/ui/variants/var_button-cta.ts +76 -0
  244. package/dist/ui/variants/var_button-destructive-ghost.ts +72 -0
  245. package/dist/ui/variants/var_button-destructive.ts +76 -0
  246. package/dist/ui/variants/var_button-fill.ts +76 -0
  247. package/dist/ui/variants/var_button-ghost.ts +72 -0
  248. package/dist/ui/variants/var_button-glass.ts +55 -0
  249. package/dist/ui/variants/var_button-normal.ts +76 -0
  250. package/dist/ui/variants/var_button-quiet.ts +74 -0
  251. package/dist/ui/variants/var_card.ts +17 -0
  252. package/dist/ui/variants/var_chip.ts +13 -0
  253. package/dist/ui/variants/var_choice.ts +15 -0
  254. package/dist/ui/variants/var_framed.ts +10 -0
  255. package/dist/ui/variants/var_glyph-plain.ts +11 -0
  256. package/dist/ui/variants/var_input.ts +43 -0
  257. package/dist/ui/variants/var_link-inline.ts +29 -0
  258. package/dist/ui/variants/var_list-row.ts +34 -0
  259. package/dist/ui/variants/var_rule.ts +10 -0
  260. package/dist/ui/variants/var_skeleton-block.ts +12 -0
  261. package/dist/ui/variants/var_spinner-turning.ts +12 -0
  262. package/dist/ui/variants/var_stat-tile.ts +13 -0
  263. package/dist/ui/variants/var_tab-bar.ts +15 -0
  264. package/dist/ui/variants/var_tap-target.ts +25 -0
  265. package/dist/ui/variants.ts +64 -0
  266. package/dist/ui/wrappers.d.ts +4 -1
  267. package/dist/ui/wrappers.js +60 -20
  268. package/dist/ui/wrappers.tsx +426 -0
  269. package/package.json +8 -2
@@ -0,0 +1,49 @@
1
+ 'use client'
2
+
3
+ import type { MessageKey } from '../content.tsx'
4
+ import type { Row } from '../charts.tsx'
5
+ import { roleClass } from '../fonts.ts'
6
+
7
+ import { type Element, element, useSurface } from '../wrappers.tsx'
8
+ import { Each } from '../elements/each.tsx'
9
+ import { shown, option, uses } from './radio-group.works.ts'
10
+
11
+
12
+ export interface RadioGroupProps {
13
+ readonly name: string
14
+ readonly labelKey: MessageKey
15
+ readonly options: readonly Row[]
16
+ readonly chosen?: string
17
+ readonly onValue?: (said: string) => void
18
+ readonly disabled?: boolean
19
+ readonly dispatch?: string
20
+ readonly input?: Readonly<Record<string, unknown>>
21
+ readonly invokeOn?: 'press' | 'shown'
22
+ }
23
+
24
+ export const RadioGroup: Element<'RadioGroup', RadioGroupProps> = element(
25
+ 'RadioGroup',
26
+ (props: RadioGroupProps, className) => {
27
+ const kept = uses(props)
28
+ const surface = useSurface({ className: roleClass(undefined, className),
29
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
30
+ holds: [
31
+ ...(kept.holds ?? []),
32
+ ],
33
+ ...(kept.animates === undefined ? {} : { animates: kept.animates }), })
34
+ return (
35
+ <div className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} {...(kept.on ?? {})} role="radiogroup" aria-label={surface.text(props.labelKey)}>
36
+ <Each rows={props.options} by={'value'}>
37
+ {(each0, at) => (
38
+ <label>
39
+ <input {...option(props, kept, each0, at)} type="radio" disabled={surface.marked('disabled')} />
40
+ <span>{shown(props, each0, surface, kept).caption}</span>
41
+ </label>
42
+ )}
43
+ </Each>
44
+ </div>
45
+ )
46
+ },
47
+ 'e-radio-group',
48
+ {"choice":"thread-choice"},
49
+ )
@@ -0,0 +1,33 @@
1
+ import { useRef } from 'react'
2
+
3
+ import { ITEM_ATTR, useRovingFocus } from '../roving-focus.ts'
4
+ import type { Row } from '../charts.tsx'
5
+ import type { Surface } from '../door.ts'
6
+ import type { RadioGroupProps } from './radio-group.tsx'
7
+
8
+ export function uses(props: RadioGroupProps): {
9
+ readonly holds?: readonly string[]
10
+ readonly animates?: boolean
11
+ readonly on: Readonly<Record<string, unknown>>
12
+ } {
13
+ const group = useRef<HTMLDivElement>(null)
14
+ useRovingFocus(group, { orientation: 'vertical' })
15
+ return {
16
+ ...(props.disabled === true ? { holds: ['disabled'] as const } : {}),
17
+ on: { ref: group },
18
+ }
19
+ }
20
+
21
+ export function option(props: RadioGroupProps, _kept: unknown, row: Row, _at: number): Readonly<Record<string, unknown>> {
22
+ return {
23
+ ...{ [ITEM_ATTR]: '' },
24
+ name: props.name,
25
+ value: String(row['value']),
26
+ checked: props.chosen === row['value'],
27
+ onChange: (): void => props.onValue?.(String(row['value'])),
28
+ }
29
+ }
30
+
31
+ export function shown(_props: RadioGroupProps, row: Row, surface: Surface, _kept?: unknown): Readonly<Record<string, string>> {
32
+ return { caption: surface.text(String(row['labelKey'])) }
33
+ }
@@ -5,4 +5,4 @@ export const Row = element('Row', (props, className) => {
5
5
  const surface = useSurface({ className,
6
6
  invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, });
7
7
  return (_jsx("div", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, children: props.children }));
8
- }, 'e-row');
8
+ }, 'e-row', {});
@@ -0,0 +1,28 @@
1
+ 'use client'
2
+
3
+ import type { ReactNode } from 'react'
4
+
5
+ import { type Element, element, useSurface } from '../wrappers.tsx'
6
+
7
+
8
+ export interface RowProps {
9
+ readonly children: ReactNode
10
+ readonly dispatch?: string
11
+ readonly input?: Readonly<Record<string, unknown>>
12
+ readonly invokeOn?: 'press' | 'shown'
13
+ }
14
+
15
+ export const Row: Element<'Row', RowProps> = element(
16
+ 'Row',
17
+ (props: RowProps, className) => {
18
+ const surface = useSurface({ className,
19
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
20
+ return (
21
+ <div className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y}>
22
+ {props.children}
23
+ </div>
24
+ )
25
+ },
26
+ 'e-row',
27
+ {},
28
+ )
@@ -12,4 +12,4 @@ export const Scatter = element('Scatter', (props, className) => {
12
12
  ],
13
13
  ...(kept.animates === undefined ? {} : { animates: kept.animates }), });
14
14
  return (_jsx("svg", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, ...(kept.on ?? {}), role: "img", ...(props.titleKey === undefined ? {} : { 'aria-label': surface.text(props.titleKey) }), children: props.rows.map((each0, at) => (_jsx("circle", { ...point(props, kept, each0, at) }, at))) }));
15
- }, 'e-scatter');
15
+ }, 'e-scatter', { "card": "thread-card" });
@@ -0,0 +1,41 @@
1
+ 'use client'
2
+
3
+ import type { MessageKey } from '../content.tsx'
4
+ import type { Row } from '../charts.tsx'
5
+ import { roleClass } from '../fonts.ts'
6
+
7
+ import { type Element, element, useSurface } from '../wrappers.tsx'
8
+ import { point, uses } from './scatter.works.ts'
9
+
10
+
11
+ export interface ScatterProps {
12
+ readonly rows: readonly Row[]
13
+ readonly x: string
14
+ readonly y: string
15
+ readonly titleKey?: MessageKey
16
+ readonly dispatch?: string
17
+ readonly input?: Readonly<Record<string, unknown>>
18
+ readonly invokeOn?: 'press' | 'shown'
19
+ }
20
+
21
+ export const Scatter: Element<'Scatter', ScatterProps> = element(
22
+ 'Scatter',
23
+ (props: ScatterProps, className) => {
24
+ const kept = uses(props)
25
+ const surface = useSurface({ className: roleClass(undefined, className),
26
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
27
+ holds: [
28
+ ...(kept.holds ?? []),
29
+ ],
30
+ ...(kept.animates === undefined ? {} : { animates: kept.animates }), })
31
+ return (
32
+ <svg className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} {...(kept.on ?? {})} role="img" {...(props.titleKey === undefined ? {} : { 'aria-label': surface.text(props.titleKey) })}>
33
+ {props.rows.map((each0, at) => (
34
+ <circle key={at} {...point(props, kept, each0, at)}></circle>
35
+ ))}
36
+ </svg>
37
+ )
38
+ },
39
+ 'e-scatter',
40
+ {"card":"thread-card"},
41
+ )
@@ -0,0 +1,38 @@
1
+ import { num, useRamp, type Row } from '../charts.tsx'
2
+ import type { ScatterProps } from './scatter.tsx'
3
+
4
+ const SIDE = 100
5
+
6
+ export function uses(props: ScatterProps): {
7
+ readonly holds?: readonly string[]
8
+ readonly animates?: boolean
9
+ readonly on?: Readonly<Record<string, unknown>>
10
+ readonly ramp: readonly string[]
11
+ } {
12
+ const ramp = useRamp(1)
13
+ return {
14
+ ...(props.rows.length === 0 ? { holds: ['empty'] as const } : {}),
15
+ on: { viewBox: `0 0 ${String(SIDE)} ${String(SIDE)}` },
16
+ ramp,
17
+ }
18
+ }
19
+
20
+ export function point(
21
+ props: ScatterProps,
22
+ kept: { readonly ramp: readonly string[] },
23
+ row: Row,
24
+ _at: number,
25
+ ): Readonly<Record<string, string | number>> {
26
+ const xs = props.rows.map((one: Row) => num(one, props.x))
27
+ const ys = props.rows.map((one: Row) => num(one, props.y))
28
+ const leastX = Math.min(...xs)
29
+ const leastY = Math.min(...ys)
30
+ const spanX = Math.max(...xs) - leastX || 1
31
+ const spanY = Math.max(...ys) - leastY || 1
32
+ return {
33
+ cx: (((num(row, props.x) - leastX) / spanX) * SIDE).toFixed(2),
34
+ cy: (SIDE - ((num(row, props.y) - leastY) / spanY) * SIDE).toFixed(2),
35
+ r: 2,
36
+ fill: kept.ramp[0] ?? 'currentColor',
37
+ }
38
+ }
@@ -2,10 +2,10 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { roleClass } from "../fonts.js";
4
4
  import { element, useSurface } from "../wrappers.js";
5
- import { Each } from "./each.js";
5
+ import { Each } from "../elements/each.js";
6
6
  import { does } from "./select.works.js";
7
7
  export const Select = element('Select', (props, className) => {
8
8
  const surface = useSurface({ className: roleClass(undefined, className),
9
9
  invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, });
10
10
  return (_jsxs("label", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, children: [_jsx("span", { children: surface.text(props.labelKey) }), props.value === undefined ? null : _jsx("select", { disabled: surface.marked('disabled'), value: props.value ?? '', onChange: (event) => does(props).chose(event.target.value), children: _jsx(Each, { rows: props.options, by: props.value, children: (each0, at) => (_jsx("option", { value: String(each0.value), children: surface.text(String(each0.labelKey)) })) }) })] }));
11
- }, 'e-select');
11
+ }, 'e-select', { "input": "thread-input" });
@@ -0,0 +1,42 @@
1
+ 'use client'
2
+
3
+ import type { MessageKey } from '../content.tsx'
4
+ import type { Row } from '../charts.tsx'
5
+ import { roleClass } from '../fonts.ts'
6
+
7
+ import { type Element, element, useSurface } from '../wrappers.tsx'
8
+ import { Each } from '../elements/each.tsx'
9
+ import { does } from './select.works.ts'
10
+
11
+
12
+ export interface SelectProps {
13
+ readonly labelKey: MessageKey
14
+ readonly options: readonly Row[]
15
+ readonly value?: string
16
+ readonly onValue?: (said: string) => void
17
+ readonly dispatch?: string
18
+ readonly input?: Readonly<Record<string, unknown>>
19
+ readonly invokeOn?: 'press' | 'shown'
20
+ }
21
+
22
+ export const Select: Element<'Select', SelectProps> = element(
23
+ 'Select',
24
+ (props: SelectProps, className) => {
25
+ const surface = useSurface({ className: roleClass(undefined, className),
26
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
27
+ return (
28
+ <label className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y}>
29
+ <span>{surface.text(props.labelKey)}</span>
30
+ {props.value === undefined ? null : <select disabled={surface.marked('disabled')} value={props.value ?? ''} onChange={(event) => does(props).chose(event.target.value)}>
31
+ <Each rows={props.options} by={props.value}>
32
+ {(each0, at) => (
33
+ <option value={String(each0.value)}>{surface.text(String(each0.labelKey))}</option>
34
+ )}
35
+ </Each>
36
+ </select>}
37
+ </label>
38
+ )
39
+ },
40
+ 'e-select',
41
+ {"input":"thread-input"},
42
+ )
@@ -0,0 +1,5 @@
1
+ import type { SelectProps } from './select.tsx'
2
+
3
+ export function does(props: SelectProps): { readonly chose: (value: string) => void } {
4
+ return { chose: (value: string) => props.onValue?.(value) }
5
+ }
@@ -6,4 +6,4 @@ export const Separator = element('Separator', (props, className) => {
6
6
  const surface = useSurface({ className: roleClass(undefined, className),
7
7
  invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, });
8
8
  return (_jsx("div", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, role: "separator", "aria-orientation": props.orientation === 'vertical' ? 'vertical' : 'horizontal', children: props.labelKey === undefined ? null : _jsx("span", { children: surface.text(props.labelKey) }) }));
9
- }, 'e-separator');
9
+ }, 'e-separator', { "rule": "thread-rule" });
@@ -0,0 +1,30 @@
1
+ 'use client'
2
+
3
+ import type { MessageKey } from '../content.tsx'
4
+ import { roleClass } from '../fonts.ts'
5
+
6
+ import { type Element, element, useSurface } from '../wrappers.tsx'
7
+
8
+
9
+ export interface SeparatorProps {
10
+ readonly labelKey?: MessageKey
11
+ readonly orientation?: string
12
+ readonly dispatch?: string
13
+ readonly input?: Readonly<Record<string, unknown>>
14
+ readonly invokeOn?: 'press' | 'shown'
15
+ }
16
+
17
+ export const Separator: Element<'Separator', SeparatorProps> = element(
18
+ 'Separator',
19
+ (props: SeparatorProps, className) => {
20
+ const surface = useSurface({ className: roleClass(undefined, className),
21
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
22
+ return (
23
+ <div className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} role="separator" aria-orientation={props.orientation === 'vertical' ? 'vertical' : 'horizontal'}>
24
+ {props.labelKey === undefined ? null : <span>{surface.text(props.labelKey)}</span>}
25
+ </div>
26
+ )
27
+ },
28
+ 'e-separator',
29
+ {"rule":"thread-rule"},
30
+ )
@@ -6,4 +6,4 @@ export const Skeleton = element('Skeleton', (props, className) => {
6
6
  const surface = useSurface({ className: roleClass(undefined, className),
7
7
  invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, });
8
8
  return (_jsx("span", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, "aria-hidden": "true", children: Array.from({ length: Math.max(1, props.lines ?? 1) }, (_, at) => (_jsx("span", {}))) }));
9
- }, 'e-skeleton');
9
+ }, 'e-skeleton', { "skeletonBlock": "thread-skeleton-block" });
@@ -0,0 +1,30 @@
1
+ 'use client'
2
+
3
+ import { roleClass } from '../fonts.ts'
4
+
5
+ import { type Element, element, useSurface } from '../wrappers.tsx'
6
+
7
+
8
+ export interface SkeletonProps {
9
+ readonly lines?: number
10
+ readonly dispatch?: string
11
+ readonly input?: Readonly<Record<string, unknown>>
12
+ readonly invokeOn?: 'press' | 'shown'
13
+ }
14
+
15
+ export const Skeleton: Element<'Skeleton', SkeletonProps> = element(
16
+ 'Skeleton',
17
+ (props: SkeletonProps, className) => {
18
+ const surface = useSurface({ className: roleClass(undefined, className),
19
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
20
+ return (
21
+ <span className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} aria-hidden="true">
22
+ {Array.from({ length: Math.max(1, props.lines ?? 1) }, (_, at) => (
23
+ <span></span>
24
+ ))}
25
+ </span>
26
+ )
27
+ },
28
+ 'e-skeleton',
29
+ {"skeletonBlock":"thread-skeleton-block"},
30
+ )
@@ -7,4 +7,4 @@ export const Slider = element('Slider', (props, className) => {
7
7
  const surface = useSurface({ className: roleClass(undefined, className),
8
8
  invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, });
9
9
  return (_jsx("input", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, type: "range", disabled: surface.marked('disabled'), value: props.value ?? 0, onChange: (event) => does(props).moved(Number(event.target.value)), min: props.min, max: props.max, step: props.step ?? 1, "aria-label": surface.text(props.labelKey) }));
10
- }, 'e-slider');
10
+ }, 'e-slider', { "input": "thread-input" });
@@ -0,0 +1,33 @@
1
+ 'use client'
2
+
3
+ import type { MessageKey } from '../content.tsx'
4
+ import { roleClass } from '../fonts.ts'
5
+
6
+ import { type Element, element, useSurface } from '../wrappers.tsx'
7
+ import { does } from './slider.works.ts'
8
+
9
+
10
+ export interface SliderProps {
11
+ readonly labelKey: MessageKey
12
+ readonly value?: number
13
+ readonly min?: number
14
+ readonly max?: number
15
+ readonly step?: number
16
+ readonly onValue?: (said: number) => void
17
+ readonly dispatch?: string
18
+ readonly input?: Readonly<Record<string, unknown>>
19
+ readonly invokeOn?: 'press' | 'shown'
20
+ }
21
+
22
+ export const Slider: Element<'Slider', SliderProps> = element(
23
+ 'Slider',
24
+ (props: SliderProps, className) => {
25
+ const surface = useSurface({ className: roleClass(undefined, className),
26
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
27
+ return (
28
+ <input className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} type="range" disabled={surface.marked('disabled')} value={props.value ?? 0} onChange={(event) => does(props).moved(Number(event.target.value))} min={props.min} max={props.max} step={props.step ?? 1} aria-label={surface.text(props.labelKey)} />
29
+ )
30
+ },
31
+ 'e-slider',
32
+ {"input":"thread-input"},
33
+ )
@@ -0,0 +1,5 @@
1
+ import type { SliderProps } from './slider.tsx'
2
+
3
+ export function does(props: SliderProps): { readonly moved: (to: number) => void } {
4
+ return { moved: (to: number) => props.onValue?.(to) }
5
+ }
@@ -12,4 +12,4 @@ export const Sparkline = element('Sparkline', (props, className) => {
12
12
  ],
13
13
  ...(kept.animates === undefined ? {} : { animates: kept.animates }), });
14
14
  return (_jsx("svg", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, ...(kept.on ?? {}), "aria-hidden": "true", children: _jsx("polyline", { ...drawing(props, kept) }) }));
15
- }, 'e-sparkline');
15
+ }, 'e-sparkline', { "card": "thread-card" });
@@ -0,0 +1,36 @@
1
+ 'use client'
2
+
3
+ import type { Row } from '../charts.tsx'
4
+ import { roleClass } from '../fonts.ts'
5
+
6
+ import { type Element, element, useSurface } from '../wrappers.tsx'
7
+ import { drawing, uses } from './sparkline.works.ts'
8
+
9
+
10
+ export interface SparklineProps {
11
+ readonly rows: readonly Row[]
12
+ readonly value: string
13
+ readonly dispatch?: string
14
+ readonly input?: Readonly<Record<string, unknown>>
15
+ readonly invokeOn?: 'press' | 'shown'
16
+ }
17
+
18
+ export const Sparkline: Element<'Sparkline', SparklineProps> = element(
19
+ 'Sparkline',
20
+ (props: SparklineProps, className) => {
21
+ const kept = uses(props)
22
+ const surface = useSurface({ className: roleClass(undefined, className),
23
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
24
+ holds: [
25
+ ...(kept.holds ?? []),
26
+ ],
27
+ ...(kept.animates === undefined ? {} : { animates: kept.animates }), })
28
+ return (
29
+ <svg className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} {...(kept.on ?? {})} aria-hidden="true">
30
+ <polyline {...drawing(props, kept)}></polyline>
31
+ </svg>
32
+ )
33
+ },
34
+ 'e-sparkline',
35
+ {"card":"thread-card"},
36
+ )
@@ -0,0 +1,32 @@
1
+ import { num, polyline, useRamp } from '../charts.tsx'
2
+ import type { Row } from '../charts.tsx'
3
+ import type { SparklineProps } from './sparkline.tsx'
4
+
5
+ const WIDE = 100
6
+ const TALL = 24
7
+
8
+ export function uses(props: SparklineProps): {
9
+ readonly holds?: readonly string[]
10
+ readonly animates?: boolean
11
+ readonly on?: Readonly<Record<string, unknown>>
12
+ readonly ramp: readonly string[]
13
+ } {
14
+ const ramp = useRamp(1)
15
+ return {
16
+ ...(props.rows.length === 0 ? { holds: ['empty'] as const } : {}),
17
+ on: { viewBox: `0 0 ${String(WIDE)} ${String(TALL)}` },
18
+ ramp,
19
+ }
20
+ }
21
+
22
+ export function drawing(
23
+ props: SparklineProps,
24
+ kept: { readonly ramp: readonly string[] },
25
+ ): Readonly<Record<string, string | number>> {
26
+ return {
27
+ points: polyline(props.rows.map((one: Row) => num(one, props.value)), WIDE, TALL),
28
+ fill: 'none',
29
+ stroke: kept.ramp[0] ?? 'currentColor',
30
+ strokeWidth: 2,
31
+ }
32
+ }
@@ -9,4 +9,4 @@ export const Spinner = element('Spinner', (props, className) => {
9
9
  'spinner',
10
10
  ], });
11
11
  return (_jsx("span", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, "aria-label": surface.text(props.labelKey), children: null }));
12
- }, 'e-spinner');
12
+ }, 'e-spinner', { "spinnerTurning": "thread-spinner-turning" });
@@ -0,0 +1,32 @@
1
+ 'use client'
2
+
3
+ import type { MessageKey } from '../content.tsx'
4
+ import { roleClass } from '../fonts.ts'
5
+
6
+ import { type Element, element, useSurface } from '../wrappers.tsx'
7
+
8
+
9
+ export interface SpinnerProps {
10
+ readonly labelKey: MessageKey
11
+ readonly dispatch?: string
12
+ readonly input?: Readonly<Record<string, unknown>>
13
+ readonly invokeOn?: 'press' | 'shown'
14
+ }
15
+
16
+ export const Spinner: Element<'Spinner', SpinnerProps> = element(
17
+ 'Spinner',
18
+ (props: SpinnerProps, className) => {
19
+ const surface = useSurface({ className: roleClass(undefined, className),
20
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
21
+ holds: [
22
+ 'spinner' as const,
23
+ ], })
24
+ return (
25
+ <span className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} aria-label={surface.text(props.labelKey)}>
26
+ {null}
27
+ </span>
28
+ )
29
+ },
30
+ 'e-spinner',
31
+ {"spinnerTurning":"thread-spinner-turning"},
32
+ )
@@ -5,4 +5,4 @@ export const Stack = element('Stack', (props, className) => {
5
5
  const surface = useSurface({ className,
6
6
  invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, });
7
7
  return (_jsx("div", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, children: props.children }));
8
- }, 'e-stack');
8
+ }, 'e-stack', {});
@@ -0,0 +1,28 @@
1
+ 'use client'
2
+
3
+ import type { ReactNode } from 'react'
4
+
5
+ import { type Element, element, useSurface } from '../wrappers.tsx'
6
+
7
+
8
+ export interface StackProps {
9
+ readonly children: ReactNode
10
+ readonly dispatch?: string
11
+ readonly input?: Readonly<Record<string, unknown>>
12
+ readonly invokeOn?: 'press' | 'shown'
13
+ }
14
+
15
+ export const Stack: Element<'Stack', StackProps> = element(
16
+ 'Stack',
17
+ (props: StackProps, className) => {
18
+ const surface = useSurface({ className,
19
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
20
+ return (
21
+ <div className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y}>
22
+ {props.children}
23
+ </div>
24
+ )
25
+ },
26
+ 'e-stack',
27
+ {},
28
+ )
@@ -7,4 +7,4 @@ export const Stat = element('Stat', (props, className) => {
7
7
  const surface = useSurface({ className: roleClass(undefined, className),
8
8
  invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, });
9
9
  return (_jsxs("figure", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, children: [_jsx("span", { children: shown(props, surface).figure }), _jsx("figcaption", { children: surface.text(props.labelKey) }), _jsx("span", { children: shown(props, surface).delta })] }));
10
- }, 'e-stat');
10
+ }, 'e-stat', { "statTile": "thread-stat-tile" });
@@ -0,0 +1,35 @@
1
+ 'use client'
2
+
3
+ import type { MessageKey } from '../content.tsx'
4
+ import { roleClass } from '../fonts.ts'
5
+
6
+ import { type Element, element, useSurface } from '../wrappers.tsx'
7
+ import { shown } from './stat.works.ts'
8
+
9
+
10
+ export interface StatProps {
11
+ readonly labelKey: MessageKey
12
+ readonly value?: unknown
13
+ readonly compare?: number
14
+ readonly format?: string
15
+ readonly dispatch?: string
16
+ readonly input?: Readonly<Record<string, unknown>>
17
+ readonly invokeOn?: 'press' | 'shown'
18
+ }
19
+
20
+ export const Stat: Element<'Stat', StatProps> = element(
21
+ 'Stat',
22
+ (props: StatProps, className) => {
23
+ const surface = useSurface({ className: roleClass(undefined, className),
24
+ invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
25
+ return (
26
+ <figure className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y}>
27
+ <span>{shown(props, surface).figure}</span>
28
+ <figcaption>{surface.text(props.labelKey)}</figcaption>
29
+ <span>{shown(props, surface).delta}</span>
30
+ </figure>
31
+ )
32
+ },
33
+ 'e-stat',
34
+ {"statTile":"thread-stat-tile"},
35
+ )
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ import { formatValue } from '../validators.ts'
4
+ import type { StatProps } from './stat.tsx'
5
+
6
+ export function shown(props: StatProps, _surface: unknown): Readonly<Record<string, ReactNode>> {
7
+ const current = typeof props.value === 'number' ? props.value : Number(props.value ?? 0)
8
+ const against = props.compare
9
+ const moved = against === undefined || against === 0 ? null : (current - against) / Math.abs(against)
10
+ return {
11
+ figure: formatValue(props.format ?? 'number', props.value),
12
+ delta: moved === null ? null : formatValue('percent', Math.round(moved * 1000) / 10),
13
+ }
14
+ }
@@ -12,4 +12,4 @@ export const Surface = element('Surface', (props, className) => {
12
12
  animates: true,
13
13
  ...(kept.animates === undefined ? {} : { animates: kept.animates }), });
14
14
  return (_jsx("div", { className: surface.className, ...surface.marks, ...surface.invokes, ...surface.a11y, ...(kept.on ?? {}), children: props.children }));
15
- }, 'e-surface');
15
+ }, 'e-surface', { "card": "thread-card" });