@prestack/thread-ui 0.1.9 → 0.1.11

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 (210) hide show
  1. package/CHANGELOG.md +366 -0
  2. package/dist/ui/attach.js +6 -7
  3. package/dist/ui/compositions.d.ts +0 -2
  4. package/dist/ui/compositions.js +2 -112
  5. package/dist/ui/generators/routes.js +1 -0
  6. package/dist/ui/variant.d.ts +1 -3
  7. package/package.json +2 -2
  8. package/dist/ui/animations/anm_appear.ts +0 -13
  9. package/dist/ui/animations/anm_blur_in.ts +0 -19
  10. package/dist/ui/animations/anm_blur_out.ts +0 -18
  11. package/dist/ui/animations/anm_dismiss.ts +0 -18
  12. package/dist/ui/animations/anm_drop.ts +0 -19
  13. package/dist/ui/animations/anm_fall.ts +0 -18
  14. package/dist/ui/animations/anm_flash.ts +0 -18
  15. package/dist/ui/animations/anm_glow.ts +0 -16
  16. package/dist/ui/animations/anm_lift.ts +0 -16
  17. package/dist/ui/animations/anm_nudge.ts +0 -16
  18. package/dist/ui/animations/anm_pop_in.ts +0 -23
  19. package/dist/ui/animations/anm_pop_out.ts +0 -22
  20. package/dist/ui/animations/anm_press.ts +0 -12
  21. package/dist/ui/animations/anm_pulse.ts +0 -13
  22. package/dist/ui/animations/anm_rise.ts +0 -19
  23. package/dist/ui/animations/anm_shake.ts +0 -13
  24. package/dist/ui/animations/anm_slide_in_left.ts +0 -19
  25. package/dist/ui/animations/anm_slide_in_right.ts +0 -19
  26. package/dist/ui/animations/anm_slide_out_left.ts +0 -18
  27. package/dist/ui/animations/anm_slide_out_right.ts +0 -18
  28. package/dist/ui/animations/anm_spin.ts +0 -12
  29. package/dist/ui/animations/anm_swell.ts +0 -16
  30. package/dist/ui/animations/anm_wobble.ts +0 -24
  31. package/dist/ui/animations/anm_zoom_in.ts +0 -19
  32. package/dist/ui/animations/anm_zoom_out.ts +0 -18
  33. package/dist/ui/animations.ts +0 -308
  34. package/dist/ui/attach.ts +0 -553
  35. package/dist/ui/charts.tsx +0 -69
  36. package/dist/ui/checked.ts +0 -32
  37. package/dist/ui/collector.ts +0 -140
  38. package/dist/ui/compositions.ts +0 -555
  39. package/dist/ui/consent.ts +0 -55
  40. package/dist/ui/content.tsx +0 -27
  41. package/dist/ui/contrast.ts +0 -27
  42. package/dist/ui/controls.tsx +0 -25
  43. package/dist/ui/disclosure.tsx +0 -20
  44. package/dist/ui/dismiss-layer.ts +0 -87
  45. package/dist/ui/door.ts +0 -140
  46. package/dist/ui/drag.ts +0 -316
  47. package/dist/ui/elements/accordion.tsx +0 -47
  48. package/dist/ui/elements/accordion.works.ts +0 -66
  49. package/dist/ui/elements/aspect-ratio.tsx +0 -31
  50. package/dist/ui/elements/aspect-ratio.works.ts +0 -5
  51. package/dist/ui/elements/avatar.tsx +0 -34
  52. package/dist/ui/elements/avatar.works.ts +0 -16
  53. package/dist/ui/elements/badge.tsx +0 -33
  54. package/dist/ui/elements/badge.works.ts +0 -9
  55. package/dist/ui/elements/bars.tsx +0 -50
  56. package/dist/ui/elements/bars.works.ts +0 -29
  57. package/dist/ui/elements/box.tsx +0 -36
  58. package/dist/ui/elements/breadcrumb.tsx +0 -38
  59. package/dist/ui/elements/breadcrumb.works.ts +0 -24
  60. package/dist/ui/elements/button.tsx +0 -46
  61. package/dist/ui/elements/button.works.tsx +0 -52
  62. package/dist/ui/elements/column.tsx +0 -29
  63. package/dist/ui/elements/consent.tsx +0 -71
  64. package/dist/ui/elements/consent.works.tsx +0 -132
  65. package/dist/ui/elements/donut.tsx +0 -45
  66. package/dist/ui/elements/donut.works.ts +0 -42
  67. package/dist/ui/elements/each.tsx +0 -34
  68. package/dist/ui/elements/each.works.tsx +0 -82
  69. package/dist/ui/elements/empty.tsx +0 -33
  70. package/dist/ui/elements/field.tsx +0 -45
  71. package/dist/ui/elements/field.works.ts +0 -65
  72. package/dist/ui/elements/funnel.tsx +0 -50
  73. package/dist/ui/elements/funnel.works.ts +0 -37
  74. package/dist/ui/elements/gauge.tsx +0 -40
  75. package/dist/ui/elements/gauge.works.ts +0 -42
  76. package/dist/ui/elements/glyph.tsx +0 -30
  77. package/dist/ui/elements/glyph.works.tsx +0 -42
  78. package/dist/ui/elements/grid.tsx +0 -29
  79. package/dist/ui/elements/heatmap.tsx +0 -48
  80. package/dist/ui/elements/heatmap.works.ts +0 -24
  81. package/dist/ui/elements/hit-box.tsx +0 -47
  82. package/dist/ui/elements/hit-box.works.tsx +0 -576
  83. package/dist/ui/elements/image.tsx +0 -29
  84. package/dist/ui/elements/line-chart.tsx +0 -45
  85. package/dist/ui/elements/line-chart.works.ts +0 -41
  86. package/dist/ui/elements/link.tsx +0 -38
  87. package/dist/ui/elements/link.works.ts +0 -25
  88. package/dist/ui/elements/media.tsx +0 -57
  89. package/dist/ui/elements/menu.tsx +0 -51
  90. package/dist/ui/elements/menu.works.tsx +0 -154
  91. package/dist/ui/elements/money.tsx +0 -36
  92. package/dist/ui/elements/money.works.ts +0 -9
  93. package/dist/ui/elements/pagination.tsx +0 -39
  94. package/dist/ui/elements/pagination.works.ts +0 -20
  95. package/dist/ui/elements/progress.tsx +0 -34
  96. package/dist/ui/elements/progress.works.ts +0 -8
  97. package/dist/ui/elements/radio-group.tsx +0 -50
  98. package/dist/ui/elements/radio-group.works.ts +0 -33
  99. package/dist/ui/elements/row.tsx +0 -29
  100. package/dist/ui/elements/scatter.tsx +0 -42
  101. package/dist/ui/elements/scatter.works.ts +0 -38
  102. package/dist/ui/elements/select.tsx +0 -43
  103. package/dist/ui/elements/select.works.ts +0 -5
  104. package/dist/ui/elements/separator.tsx +0 -31
  105. package/dist/ui/elements/skeleton.tsx +0 -31
  106. package/dist/ui/elements/slider.tsx +0 -34
  107. package/dist/ui/elements/slider.works.ts +0 -5
  108. package/dist/ui/elements/sparkline.tsx +0 -37
  109. package/dist/ui/elements/sparkline.works.ts +0 -32
  110. package/dist/ui/elements/spinner.tsx +0 -33
  111. package/dist/ui/elements/stack.tsx +0 -29
  112. package/dist/ui/elements/stat.tsx +0 -36
  113. package/dist/ui/elements/stat.works.ts +0 -14
  114. package/dist/ui/elements/surface.tsx +0 -36
  115. package/dist/ui/elements/surface.works.ts +0 -9
  116. package/dist/ui/elements/table.tsx +0 -62
  117. package/dist/ui/elements/table.works.ts +0 -30
  118. package/dist/ui/elements/tabs.tsx +0 -47
  119. package/dist/ui/elements/tabs.works.ts +0 -84
  120. package/dist/ui/elements/text.tsx +0 -33
  121. package/dist/ui/elements/textarea.tsx +0 -38
  122. package/dist/ui/elements/textarea.works.ts +0 -5
  123. package/dist/ui/elements/time.tsx +0 -40
  124. package/dist/ui/elements/time.works.ts +0 -29
  125. package/dist/ui/elements/toggle.tsx +0 -34
  126. package/dist/ui/elements/toggle.works.ts +0 -5
  127. package/dist/ui/elements/tooltip.tsx +0 -40
  128. package/dist/ui/elements/tooltip.works.ts +0 -77
  129. package/dist/ui/elements/value.tsx +0 -38
  130. package/dist/ui/elements/value.works.ts +0 -9
  131. package/dist/ui/elements.ts +0 -127
  132. package/dist/ui/focus-scope.ts +0 -121
  133. package/dist/ui/fonts.ts +0 -355
  134. package/dist/ui/generators/dev.d.ts +0 -1
  135. package/dist/ui/generators/dev.js +0 -61
  136. package/dist/ui/generators/dev.ts +0 -74
  137. package/dist/ui/generators/elements.ts +0 -796
  138. package/dist/ui/generators/i18n.ts +0 -283
  139. package/dist/ui/generators/icons.ts +0 -207
  140. package/dist/ui/generators/react.ts +0 -267
  141. package/dist/ui/generators/routes.ts +0 -847
  142. package/dist/ui/generators/show.ts +0 -261
  143. package/dist/ui/generators/styles.ts +0 -677
  144. package/dist/ui/generators/variants.ts +0 -196
  145. package/dist/ui/i18n/catalogs/en.ts +0 -191
  146. package/dist/ui/i18n/format.ts +0 -221
  147. package/dist/ui/i18n/locales.ts +0 -33
  148. package/dist/ui/i18n/parse.ts +0 -315
  149. package/dist/ui/i18n/translator.ts +0 -31
  150. package/dist/ui/i18n/types.ts +0 -96
  151. package/dist/ui/icons.ts +0 -331
  152. package/dist/ui/islands/map.ts +0 -58
  153. package/dist/ui/localizations.ts +0 -75
  154. package/dist/ui/material.ts +0 -236
  155. package/dist/ui/materials/mat_bordered.ts +0 -13
  156. package/dist/ui/materials/mat_ceramic.ts +0 -13
  157. package/dist/ui/materials/mat_clay.ts +0 -13
  158. package/dist/ui/materials/mat_elevated.ts +0 -24
  159. package/dist/ui/materials/mat_flat.ts +0 -34
  160. package/dist/ui/materials/mat_glass.ts +0 -20
  161. package/dist/ui/materials/mat_lit.ts +0 -13
  162. package/dist/ui/materials/mat_moulded.ts +0 -11
  163. package/dist/ui/materials.ts +0 -197
  164. package/dist/ui/modes.ts +0 -44
  165. package/dist/ui/navigation.tsx +0 -29
  166. package/dist/ui/positioning.ts +0 -90
  167. package/dist/ui/presented.tsx +0 -119
  168. package/dist/ui/provider.tsx +0 -184
  169. package/dist/ui/render-loop.ts +0 -133
  170. package/dist/ui/roving-focus.ts +0 -161
  171. package/dist/ui/screens.ts +0 -141
  172. package/dist/ui/scroll-lock.ts +0 -28
  173. package/dist/ui/series.ts +0 -97
  174. package/dist/ui/signals.ts +0 -386
  175. package/dist/ui/styleguide.ts +0 -231
  176. package/dist/ui/styleguides.ts +0 -374
  177. package/dist/ui/themes.ts +0 -22
  178. package/dist/ui/token.ts +0 -78
  179. package/dist/ui/tokens/shadow.ts +0 -25
  180. package/dist/ui/tokens.ts +0 -234
  181. package/dist/ui/validators.ts +0 -232
  182. package/dist/ui/variant.ts +0 -352
  183. package/dist/ui/variants/var_avatar-round.ts +0 -14
  184. package/dist/ui/variants/var_bubble-me.ts +0 -14
  185. package/dist/ui/variants/var_bubble-them.ts +0 -13
  186. package/dist/ui/variants/var_button-border.ts +0 -76
  187. package/dist/ui/variants/var_button-cta.ts +0 -76
  188. package/dist/ui/variants/var_button-destructive-ghost.ts +0 -72
  189. package/dist/ui/variants/var_button-destructive.ts +0 -76
  190. package/dist/ui/variants/var_button-fill.ts +0 -76
  191. package/dist/ui/variants/var_button-ghost.ts +0 -72
  192. package/dist/ui/variants/var_button-glass.ts +0 -55
  193. package/dist/ui/variants/var_button-normal.ts +0 -76
  194. package/dist/ui/variants/var_button-quiet.ts +0 -74
  195. package/dist/ui/variants/var_card.ts +0 -17
  196. package/dist/ui/variants/var_chip.ts +0 -13
  197. package/dist/ui/variants/var_choice.ts +0 -15
  198. package/dist/ui/variants/var_framed.ts +0 -10
  199. package/dist/ui/variants/var_glyph-plain.ts +0 -11
  200. package/dist/ui/variants/var_input.ts +0 -43
  201. package/dist/ui/variants/var_link-inline.ts +0 -29
  202. package/dist/ui/variants/var_list-row.ts +0 -34
  203. package/dist/ui/variants/var_rule.ts +0 -10
  204. package/dist/ui/variants/var_skeleton-block.ts +0 -12
  205. package/dist/ui/variants/var_spinner-turning.ts +0 -12
  206. package/dist/ui/variants/var_stat-tile.ts +0 -13
  207. package/dist/ui/variants/var_tab-bar.ts +0 -15
  208. package/dist/ui/variants/var_tap-target.ts +0 -25
  209. package/dist/ui/variants.ts +0 -64
  210. package/dist/ui/wrappers.tsx +0 -429
@@ -1,5 +0,0 @@
1
- import type { AspectRatioProps } from './aspect-ratio.tsx'
2
-
3
- export function measured(props: AspectRatioProps): Readonly<Record<string, string | number>> {
4
- return { ratio: props.ratio }
5
- }
@@ -1,34 +0,0 @@
1
- 'use client'
2
-
3
- import type { MessageKey } from '../content.tsx'
4
- import { roleClass } from '../fonts.ts'
5
-
6
- import type { Dispatching } from '../checked.ts'
7
- import { type Element, element, useSurface } from '../wrappers.tsx'
8
- import { shown } from './avatar.works.ts'
9
-
10
-
11
- export interface AvatarProps {
12
- readonly labelKey: MessageKey
13
- readonly src?: string
14
- readonly initials?: string
15
- readonly dispatch?: keyof Dispatching
16
- readonly input?: Readonly<Record<string, unknown>>
17
- readonly invokeOn?: 'press' | 'shown'
18
- }
19
-
20
- export const Avatar: Element<'Avatar', AvatarProps> = element(
21
- 'Avatar',
22
- (props: AvatarProps, 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
- <span className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} role="img" aria-label={surface.text(props.labelKey)}>
27
- {props.src === undefined ? null : <img src={props.src} alt="" />}
28
- <span>{shown(props, surface).lettering}</span>
29
- </span>
30
- )
31
- },
32
- 'e-avatar',
33
- {"avatarRound":"thread-avatar-round"},
34
- )
@@ -1,16 +0,0 @@
1
- import type { AvatarProps } from './avatar.tsx'
2
-
3
- export function shown(props: AvatarProps, surface: { readonly text: (key: AvatarProps['labelKey']) => string }): Readonly<Record<string, string | null>> {
4
- if (props.src !== undefined) return { lettering: null }
5
- const said = props.initials
6
- if (said !== undefined) return { lettering: said }
7
- return {
8
- lettering: surface
9
- .text(props.labelKey)
10
- .split(/\s+/)
11
- .filter(Boolean)
12
- .slice(0, 2)
13
- .map((part) => part.charAt(0).toUpperCase())
14
- .join(''),
15
- }
16
- }
@@ -1,33 +0,0 @@
1
- 'use client'
2
-
3
- import type { MessageKey } from '../content.tsx'
4
- import { roleClass } from '../fonts.ts'
5
-
6
- import type { Dispatching } from '../checked.ts'
7
- import { type Element, element, useSurface } from '../wrappers.tsx'
8
- import { shows } from './badge.works.ts'
9
-
10
-
11
- export interface BadgeProps {
12
- readonly labelKey: MessageKey
13
- readonly count?: number
14
- readonly max?: number
15
- readonly dispatch?: keyof Dispatching
16
- readonly input?: Readonly<Record<string, unknown>>
17
- readonly invokeOn?: 'press' | 'shown'
18
- }
19
-
20
- export const Badge: Element<'Badge', BadgeProps> = element(
21
- 'Badge',
22
- (props: BadgeProps, 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
- <span className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y}>
27
- {shows(props, surface)}
28
- </span>
29
- )
30
- },
31
- 'e-badge',
32
- {"chip":"thread-chip"},
33
- )
@@ -1,9 +0,0 @@
1
- import type { ReactNode } from 'react'
2
-
3
- import type { BadgeProps } from './badge.tsx'
4
-
5
- export function shows(props: BadgeProps, surface: { readonly text: (key: BadgeProps['labelKey']) => string }): ReactNode {
6
- const max = props.max ?? 99
7
- if (props.count === undefined) return surface.text(props.labelKey)
8
- return props.count > max ? `${max}+` : String(props.count)
9
- }
@@ -1,50 +0,0 @@
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
- import { measured as marking } from '../charts.tsx'
7
-
8
- import type { Dispatching } from '../checked.ts'
9
- import { type Element, element, useSurface } from '../wrappers.tsx'
10
- import { Each } from '../elements/each.tsx'
11
- import { shown, sized, uses } from './bars.works.ts'
12
-
13
-
14
- export interface BarsProps {
15
- readonly rows: readonly Row[]
16
- readonly by: string
17
- readonly value: string
18
- readonly format?: string
19
- readonly titleKey?: MessageKey
20
- readonly dispatch?: keyof Dispatching
21
- readonly input?: Readonly<Record<string, unknown>>
22
- readonly invokeOn?: 'press' | 'shown'
23
- }
24
-
25
- export const Bars: Element<'Bars', BarsProps> = element(
26
- 'Bars',
27
- (props: BarsProps, className) => {
28
- const kept = uses(props)
29
- const surface = useSurface({ className: roleClass(undefined, className),
30
- invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
31
- holds: [
32
- ...(kept.holds ?? []),
33
- ],
34
- ...(kept.animates === undefined ? {} : { animates: kept.animates }), })
35
- return (
36
- <div className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} {...(kept.on ?? {})} role="img" {...(props.titleKey === undefined ? {} : { 'aria-label': surface.text(props.titleKey) })}>
37
- <Each rows={props.rows} by={props.by}>
38
- {(each0, at) => (
39
- <span style={marking(sized(props, kept, each0, at))}>
40
- <span>{shown(props, each0, surface, kept).label}</span>
41
- <span>{shown(props, each0, surface, kept).amount}</span>
42
- </span>
43
- )}
44
- </Each>
45
- </div>
46
- )
47
- },
48
- 'e-bars',
49
- {"card":"thread-card"},
50
- )
@@ -1,29 +0,0 @@
1
- import { formatValue } from '../validators.ts'
2
- import { seriesColour } from '../series.ts'
3
- import { num, str, useRamp, type Row } from '../charts.tsx'
4
- import type { BarsProps } from './bars.tsx'
5
-
6
- export function uses(props: BarsProps): {
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(props.rows.length)
13
- return { ...(props.rows.length === 0 ? { holds: ['empty'] as const } : {}), ramp }
14
- }
15
-
16
- export function sized(props: BarsProps, kept: { readonly ramp: readonly string[] }, row: Row, at: number): Readonly<Record<string, string | number>> {
17
- const most = Math.max(...props.rows.map((one: Row) => num(one, props.value)), 0) || 1
18
- return {
19
- series: seriesColour(kept.ramp, at),
20
- fraction: `${((num(row, props.value) / most) * 100).toFixed(1)}%`,
21
- }
22
- }
23
-
24
- export function shown(props: BarsProps, row: Row, _surface: unknown, _kept?: unknown): Readonly<Record<string, string>> {
25
- return {
26
- label: str(row, props.by),
27
- amount: String(formatValue(props.format ?? 'number', num(row, props.value))),
28
- }
29
- }
@@ -1,36 +0,0 @@
1
- 'use client'
2
-
3
- import type { ReactNode } from 'react'
4
- import type { MessageKey } from '../content.tsx'
5
-
6
- import type { Dispatching } from '../checked.ts'
7
- import { type Element, element, useSurface } from '../wrappers.tsx'
8
-
9
-
10
- export interface BoxProps {
11
- readonly children: ReactNode
12
- readonly labelKey?: MessageKey
13
- readonly scrolling?: boolean
14
- readonly dispatch?: keyof Dispatching
15
- readonly input?: Readonly<Record<string, unknown>>
16
- readonly invokeOn?: 'press' | 'shown'
17
- }
18
-
19
- export const Box: Element<'Box', BoxProps> = element(
20
- 'Box',
21
- (props: BoxProps, className) => {
22
- const surface = useSurface({ className,
23
- invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
24
- holds: [
25
- ...(props.scrolling === true ? ['scrolling' as const] : []),
26
- ],
27
- raises: ['scrolling' as const], })
28
- return (
29
- <div className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} {...(props.labelKey === undefined ? {} : { role: 'group' as const })} {...(props.labelKey === undefined ? {} : { 'aria-label': surface.text(props.labelKey) })}>
30
- {props.children}
31
- </div>
32
- )
33
- },
34
- 'e-box',
35
- {"card":"thread-card","listRow":"thread-list-row","bubbleThem":"thread-bubble-them","bubbleMe":"thread-bubble-me"},
36
- )
@@ -1,38 +0,0 @@
1
- 'use client'
2
-
3
- import { roleClass } from '../fonts.ts'
4
- import type { MapIsland } from '../islands/map.ts'
5
- import { Link } from './link.tsx'
6
-
7
- import type { Dispatching } from '../checked.ts'
8
- import { type Element, element, useSurface } from '../wrappers.tsx'
9
- import { Each } from '../elements/each.tsx'
10
- import { crumb, steps } from './breadcrumb.works.ts'
11
-
12
-
13
- export interface BreadcrumbProps {
14
- readonly map: MapIsland
15
- readonly current: string
16
- readonly dispatch?: keyof Dispatching
17
- readonly input?: Readonly<Record<string, unknown>>
18
- readonly invokeOn?: 'press' | 'shown'
19
- }
20
-
21
- export const Breadcrumb: Element<'Breadcrumb', BreadcrumbProps> = element(
22
- 'Breadcrumb',
23
- (props: BreadcrumbProps, className) => {
24
- const surface = useSurface({ className: roleClass(undefined, className),
25
- invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
26
- return (
27
- <nav className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} aria-label={surface.text('nav.breadcrumb')}>
28
- <Each rows={steps(props)} by={'id'}>
29
- {(each0, at) => (
30
- <Link.linkInline {...crumb(props, each0, at)}></Link.linkInline>
31
- )}
32
- </Each>
33
- </nav>
34
- )
35
- },
36
- 'e-breadcrumb',
37
- {"tabBar":"thread-tab-bar"},
38
- )
@@ -1,24 +0,0 @@
1
- import { trailTo } from '../navigation.tsx'
2
- import type { Row } from '../charts.tsx'
3
- import type { BreadcrumbProps } from './breadcrumb.tsx'
4
- import type { LinkProps } from './link.tsx'
5
-
6
- export function steps(props: BreadcrumbProps): readonly Row[] {
7
- const known = new Map(props.map.screens.map((one) => [one.id, one]))
8
- if (!known.has(props.current)) return []
9
- const trail = trailTo(props.map, props.current)
10
- return trail.flatMap((id, at) => {
11
- const screen = known.get(id)
12
- if (screen === undefined) return []
13
- return [{ id, nameKey: screen.nameKey, here: at === trail.length - 1 }]
14
- })
15
- }
16
-
17
- export function crumb(_props: BreadcrumbProps, row: Row, _at: number): LinkProps & { readonly 'aria-current'?: 'page' } {
18
- return {
19
- navigateTo: String(row['id']),
20
- labelKey: String(row['nameKey']),
21
- is: 'label',
22
- ...(row['here'] === true ? ({ 'aria-current': 'page' } as const) : {}),
23
- }
24
- }
@@ -1,46 +0,0 @@
1
- 'use client'
2
-
3
- import type { MessageKey } from '../content.tsx'
4
- import { roleClass } from '../fonts.ts'
5
-
6
- import type { Dispatching } from '../checked.ts'
7
- import { type Element, element, useSurface } from '../wrappers.tsx'
8
- import { shown, iconed, worded, uses, wires } from './button.works.tsx'
9
-
10
-
11
- export interface ButtonProps {
12
- readonly label: MessageKey
13
- readonly with?: Readonly<Record<string, unknown>>
14
- readonly icon?: string
15
- readonly shows?: string
16
- readonly type?: string
17
- readonly disabled?: boolean
18
- readonly loading?: boolean
19
- readonly input?: Readonly<Record<string, unknown>>
20
- readonly navigateTo?: string
21
- readonly onPress?: () => void
22
- readonly dispatch?: keyof Dispatching
23
- readonly invokeOn?: 'press' | 'shown'
24
- }
25
-
26
- export const Button: Element<'Button', ButtonProps> = element(
27
- 'Button',
28
- (props: ButtonProps, className) => {
29
- const kept = uses(props)
30
- const surface = useSurface({ className: roleClass(undefined, className),
31
- invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
32
- holds: [
33
- ...(kept.holds ?? []),
34
- ],
35
- ...(kept.animates === undefined ? {} : { animates: kept.animates }), })
36
- const wired = wires(props, kept, surface)
37
- return (
38
- <button className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} {...(kept.on ?? {})} {...(wired.on ?? {})}>
39
- {!iconed(props, kept) ? null : <span className="e-button-symbol">{shown(props, surface, kept, wired).symbol}</span>}
40
- {!worded(props, kept) ? null : <span>{shown(props, surface, kept, wired).wording}</span>}
41
- </button>
42
- )
43
- },
44
- 'e-button',
45
- {"buttonFill":"thread-button-fill","buttonNormal":"thread-button-normal","buttonGhost":"thread-button-ghost","buttonBorder":"thread-button-border","buttonDestructive":"thread-button-destructive","buttonDestructiveGhost":"thread-button-destructive-ghost","buttonCta":"thread-button-cta","buttonQuiet":"thread-button-quiet","buttonGlass":"thread-button-glass"},
46
- )
@@ -1,52 +0,0 @@
1
- import type { ReactNode } from 'react'
2
-
3
- import { pressOf, usePress } from '../wrappers.tsx'
4
- import type { Surface } from '../door.ts'
5
- import { drawn } from './glyph.works.tsx'
6
- import type { ButtonProps } from './button.tsx'
7
-
8
- export function uses(props: ButtonProps): {
9
- readonly holds?: readonly string[]
10
- readonly animates?: boolean
11
- readonly on?: Readonly<Record<string, unknown>>
12
- readonly press: (() => void) | undefined
13
- } {
14
- return {
15
- holds: [
16
- ...(props.disabled === true ? (['disabled'] as const) : []),
17
- ...(props.loading === true ? (['loading'] as const) : []),
18
- ],
19
- press: usePress(pressOf(props), { element: 'Button', name: props.label }),
20
- }
21
- }
22
-
23
- export function wires(
24
- props: ButtonProps,
25
- kept: { readonly press: (() => void) | undefined },
26
- surface: Surface,
27
- ): { readonly on: Readonly<Record<string, unknown>> } {
28
- const inert = surface.marked('disabled') || surface.marked('loading')
29
- return {
30
- on: {
31
- type: props.type ?? 'button',
32
- disabled: inert,
33
- ...(props.shows === 'icon' ? { 'aria-label': surface.text(props.label, props.with) } : {}),
34
- onClick: inert ? undefined : kept.press,
35
- },
36
- }
37
- }
38
-
39
- export function iconed(props: ButtonProps, _kept?: unknown): boolean {
40
- return props.icon !== undefined
41
- }
42
-
43
- export function worded(props: ButtonProps, _kept?: unknown): boolean {
44
- return props.shows !== 'icon'
45
- }
46
-
47
- export function shown(props: ButtonProps, surface: Surface, _kept: unknown, _wired?: unknown): Readonly<Record<string, ReactNode>> {
48
- return {
49
- symbol: props.icon === undefined ? null : drawn(props.icon, { 'aria-hidden': true }),
50
- wording: props.shows === 'icon' ? null : surface.text(props.label, props.with),
51
- }
52
- }
@@ -1,29 +0,0 @@
1
- 'use client'
2
-
3
- import type { ReactNode } from 'react'
4
-
5
- import type { Dispatching } from '../checked.ts'
6
- import { type Element, element, useSurface } from '../wrappers.tsx'
7
-
8
-
9
- export interface ColumnProps {
10
- readonly children: ReactNode
11
- readonly dispatch?: keyof Dispatching
12
- readonly input?: Readonly<Record<string, unknown>>
13
- readonly invokeOn?: 'press' | 'shown'
14
- }
15
-
16
- export const Column: Element<'Column', ColumnProps> = element(
17
- 'Column',
18
- (props: ColumnProps, className) => {
19
- const surface = useSurface({ className,
20
- invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) }, })
21
- return (
22
- <div className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y}>
23
- {props.children}
24
- </div>
25
- )
26
- },
27
- 'e-column',
28
- {},
29
- )
@@ -1,71 +0,0 @@
1
- 'use client'
2
-
3
- import type { MessageKey } from '../content.tsx'
4
- import { roleClass } from '../fonts.ts'
5
- import type { ConsentDecision } from '../consent.ts'
6
- import { Box } from './box.tsx'
7
- import { Column } from './column.tsx'
8
- import { Text } from './text.tsx'
9
- import { Toggle } from './toggle.tsx'
10
- import { Button } from './button.tsx'
11
-
12
- import type { Dispatching } from '../checked.ts'
13
- import { type Element, element, useSurface } from '../wrappers.tsx'
14
- import { Each } from '../elements/each.tsx'
15
- import { title, policy, hasPolicy, categories, label, describe, chooser, optional, fixed, required, withdraw, withdrawable, decline, accept, acceptAll, uses } from './consent.works.tsx'
16
-
17
-
18
- export interface ConsentProps {
19
- readonly decision?: ConsentDecision
20
- readonly onDecide: (said: ConsentDecision) => void
21
- readonly policyKey?: MessageKey
22
- readonly preselected: readonly string[]
23
- readonly dispatch?: keyof Dispatching
24
- readonly input?: Readonly<Record<string, unknown>>
25
- readonly invokeOn?: 'press' | 'shown'
26
- }
27
-
28
- export const Consent: Element<'Consent', ConsentProps> = element(
29
- 'Consent',
30
- (props: ConsentProps, className) => {
31
- const kept = uses(props)
32
- useSurface({ className: roleClass(undefined, className),
33
- invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
34
- holds: [
35
- ...(kept.holds ?? []),
36
- ],
37
- ...(kept.animates === undefined ? {} : { animates: kept.animates }), })
38
- return (
39
- <>
40
- <Box.card>
41
- <Column>
42
- <Text {...title(props, kept)}></Text>
43
- {!hasPolicy(props, kept) ? null : <Text {...policy(props, kept)}></Text>}
44
- <Column>
45
- <Each rows={categories(props, kept)} by={'id'}>
46
- {(each0, at) => (
47
- <Box>
48
- <Column>
49
- <Text {...label(props, kept, each0, at)}></Text>
50
- <Text {...describe(props, kept, each0, at)}></Text>
51
- </Column>
52
- {!optional(props, kept, each0) ? null : <Toggle.input {...chooser(props, kept, each0, at)}></Toggle.input>}
53
- {!required(props, kept, each0) ? null : <Text {...fixed(props, kept, each0, at)}></Text>}
54
- </Box>
55
- )}
56
- </Each>
57
- </Column>
58
- <Box>
59
- {!withdrawable(props, kept) ? null : <Button.buttonQuiet {...withdraw(props, kept)}></Button.buttonQuiet>}
60
- <Button.buttonBorder {...decline(props, kept)}></Button.buttonBorder>
61
- <Button.buttonBorder {...accept(props, kept)}></Button.buttonBorder>
62
- <Button.buttonFill {...acceptAll(props, kept)}></Button.buttonFill>
63
- </Box>
64
- </Column>
65
- </Box.card>
66
- </>
67
- )
68
- },
69
- 'e-consent',
70
- {},
71
- )
@@ -1,132 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
-
5
- import { consentCategories, type ConsentCategory, type ConsentDecision } from '../consent.ts'
6
- import type { Row } from '../charts.tsx'
7
- import type { ButtonProps } from './button.tsx'
8
- import type { ConsentProps } from './consent.tsx'
9
- import type { TextProps } from './text.tsx'
10
- import type { ToggleProps } from './toggle.tsx'
11
-
12
- type Kept = {
13
- readonly categories: readonly ConsentCategory[]
14
- readonly selected: readonly string[]
15
- readonly accepted: boolean
16
- readonly offered: readonly string[]
17
- readonly toggle: (id: string, on: boolean) => void
18
- readonly decide: (decision: ConsentDecision['decision'], accepted: readonly string[]) => void
19
- }
20
-
21
- function firstSelection(
22
- categories: readonly ConsentCategory[],
23
- decision: ConsentDecision | undefined,
24
- preselected: readonly string[],
25
- ): readonly string[] {
26
- const answered = decision !== undefined
27
- return categories
28
- .filter(
29
- (one) =>
30
- one.required ||
31
- (answered
32
- ? decision.decision === 'accepted' && decision.accepted.includes(one.id)
33
- : preselected.includes(one.id)),
34
- )
35
- .map((one) => one.id)
36
- }
37
-
38
- export function uses(props: ConsentProps): {
39
- readonly holds?: readonly string[]
40
- readonly animates?: boolean
41
- readonly on?: Readonly<Record<string, unknown>>
42
- readonly categories: readonly ConsentCategory[]
43
- readonly selected: readonly string[]
44
- readonly accepted: boolean
45
- readonly offered: readonly string[]
46
- readonly toggle: (id: string, on: boolean) => void
47
- readonly decide: (decision: ConsentDecision['decision'], accepted: readonly string[]) => void
48
- } {
49
- const categories = consentCategories()
50
- const [selected, setSelected] = useState<readonly string[]>(() =>
51
- firstSelection(categories, props.decision, props.preselected ?? []),
52
- )
53
- const offered = categories.map((one) => one.id)
54
-
55
- return {
56
- categories,
57
- selected,
58
- offered,
59
- accepted: props.decision?.decision === 'accepted',
60
- toggle: (id: string, on: boolean): void => {
61
- setSelected((was) => (on ? [...was, id] : was.filter((one) => one !== id)))
62
- },
63
- decide: (decision: ConsentDecision['decision'], accepted: readonly string[]): void => {
64
- props.onDecide({ decision, accepted: [...accepted], offered })
65
- },
66
- }
67
- }
68
-
69
- export function categories(_props: ConsentProps, kept: Kept): readonly Row[] {
70
- return kept.categories as unknown as readonly Row[]
71
- }
72
-
73
- export function hasPolicy(props: ConsentProps, _kept: Kept): boolean {
74
- return props.policyKey !== undefined
75
- }
76
-
77
- export function withdrawable(_props: ConsentProps, kept: Kept): boolean {
78
- return kept.accepted
79
- }
80
-
81
- export function optional(_props: ConsentProps, _kept: Kept, row: Row): boolean {
82
- return row['required'] !== true
83
- }
84
-
85
- export function required(_props: ConsentProps, _kept: Kept, row: Row): boolean {
86
- return row['required'] === true
87
- }
88
-
89
- export function title(_props: ConsentProps, _kept: Kept, _at?: number): TextProps {
90
- return { k: 'consent.title', is: 'heading' }
91
- }
92
-
93
- export function policy(props: ConsentProps, _kept: Kept, _at?: number): TextProps {
94
- return { k: props.policyKey ?? 'consent.title', is: 'body' }
95
- }
96
-
97
- export function label(_props: ConsentProps, _kept: Kept, row: Row, _at: number): TextProps {
98
- return { k: String(row['labelKey']), is: 'label' }
99
- }
100
-
101
- export function describe(_props: ConsentProps, _kept: Kept, row: Row, _at: number): TextProps {
102
- return { k: String(row['describeKey']), is: 'body' }
103
- }
104
-
105
- export function fixed(_props: ConsentProps, _kept: Kept, _row: Row, _at: number): TextProps {
106
- return { k: 'consent.required', is: 'label' }
107
- }
108
-
109
- export function chooser(_props: ConsentProps, kept: Kept, row: Row, _at?: number): ToggleProps {
110
- const id = String(row['id'])
111
- return {
112
- labelKey: String(row['labelKey']),
113
- on: kept.selected.includes(id),
114
- onToggle: (on: boolean): void => kept.toggle(id, on),
115
- }
116
- }
117
-
118
- export function withdraw(_props: ConsentProps, kept: Kept): ButtonProps {
119
- return { label: 'consent.withdraw', onPress: (): void => kept.decide('withdrawn', []) }
120
- }
121
-
122
- export function decline(_props: ConsentProps, kept: Kept): ButtonProps {
123
- return { label: 'consent.decline', onPress: (): void => kept.decide('declined', []) }
124
- }
125
-
126
- export function accept(_props: ConsentProps, kept: Kept): ButtonProps {
127
- return { label: 'consent.accept', onPress: (): void => kept.decide('accepted', kept.selected) }
128
- }
129
-
130
- export function acceptAll(_props: ConsentProps, kept: Kept): ButtonProps {
131
- return { label: 'consent.acceptAll', onPress: (): void => kept.decide('accepted', kept.offered) }
132
- }
@@ -1,45 +0,0 @@
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 { Dispatching } from '../checked.ts'
8
- import { type Element, element, useSurface } from '../wrappers.tsx'
9
- import { Each } from '../elements/each.tsx'
10
- import { slice, uses } from './donut.works.ts'
11
-
12
-
13
- export interface DonutProps {
14
- readonly rows: readonly Row[]
15
- readonly by: string
16
- readonly value: string
17
- readonly titleKey?: MessageKey
18
- readonly dispatch?: keyof Dispatching
19
- readonly input?: Readonly<Record<string, unknown>>
20
- readonly invokeOn?: 'press' | 'shown'
21
- }
22
-
23
- export const Donut: Element<'Donut', DonutProps> = element(
24
- 'Donut',
25
- (props: DonutProps, className) => {
26
- const kept = uses(props)
27
- const surface = useSurface({ className: roleClass(undefined, className),
28
- invokes: { ...(props.dispatch === undefined ? {} : { dispatch: props.dispatch }), ...(props.input === undefined ? {} : { input: props.input }), ...(props.invokeOn === undefined ? {} : { on: props.invokeOn }) },
29
- holds: [
30
- ...(kept.holds ?? []),
31
- ],
32
- ...(kept.animates === undefined ? {} : { animates: kept.animates }), })
33
- return (
34
- <svg className={surface.className} {...surface.marks} {...surface.invokes} {...surface.a11y} {...(kept.on ?? {})} role="img" {...(props.titleKey === undefined ? {} : { 'aria-label': surface.text(props.titleKey) })}>
35
- <Each rows={props.rows} by={props.by}>
36
- {(each0, at) => (
37
- <circle {...slice(props, kept, each0, at)}></circle>
38
- )}
39
- </Each>
40
- </svg>
41
- )
42
- },
43
- 'e-donut',
44
- {"card":"thread-card"},
45
- )