@nanisoft/prism-ui 0.10.1 → 0.13.0
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.
- package/LICENSE +21 -21
- package/dist/.tsbuildinfo +1 -1
- package/dist/blocks/app-shell-01/app-shell.js +4 -4
- package/dist/blocks/app-shell-01/index.d.ts +2 -2
- package/dist/blocks/app-shell-01/index.js +1 -1
- package/dist/blocks/auth-form-01/auth-form.d.ts +11 -1
- package/dist/blocks/auth-form-01/auth-form.d.ts.map +1 -1
- package/dist/blocks/auth-form-01/auth-form.js +11 -8
- package/dist/blocks/auth-form-01/index.d.ts +2 -2
- package/dist/blocks/auth-form-01/index.js +1 -1
- package/dist/blocks/cta-01/cta.d.ts +26 -21
- package/dist/blocks/cta-01/cta.d.ts.map +1 -1
- package/dist/blocks/cta-01/cta.js +2 -2
- package/dist/blocks/cta-01/index.d.ts +2 -2
- package/dist/blocks/cta-01/index.js +1 -1
- package/dist/blocks/data-table-01/data-table.js +7 -7
- package/dist/blocks/data-table-01/index.d.ts +2 -2
- package/dist/blocks/data-table-01/index.js +1 -1
- package/dist/blocks/empty-state-01/empty-state.d.ts +143 -0
- package/dist/blocks/empty-state-01/empty-state.d.ts.map +1 -0
- package/dist/blocks/empty-state-01/empty-state.js +104 -0
- package/dist/blocks/empty-state-01/index.d.ts +3 -0
- package/dist/blocks/empty-state-01/index.d.ts.map +1 -0
- package/dist/blocks/empty-state-01/index.js +1 -0
- package/dist/blocks/feature-grid-01/feature-grid.d.ts +28 -1
- package/dist/blocks/feature-grid-01/feature-grid.d.ts.map +1 -1
- package/dist/blocks/feature-grid-01/feature-grid.js +34 -3
- package/dist/blocks/feature-grid-01/index.d.ts +2 -2
- package/dist/blocks/feature-grid-01/index.js +1 -1
- package/dist/blocks/hero-01/hero.d.ts +49 -17
- package/dist/blocks/hero-01/hero.d.ts.map +1 -1
- package/dist/blocks/hero-01/hero.js +14 -9
- package/dist/blocks/hero-01/index.d.ts +2 -1
- package/dist/blocks/hero-01/index.d.ts.map +1 -1
- package/dist/blocks/hero-01/index.js +1 -1
- package/dist/blocks/index.d.ts +20 -20
- package/dist/blocks/index.js +19 -19
- package/dist/blocks/instrument-panel-01/index.d.ts +2 -2
- package/dist/blocks/instrument-panel-01/index.js +1 -1
- package/dist/blocks/instrument-panel-01/instrument-panel.js +1 -1
- package/dist/blocks/logo-strip-01/index.d.ts +2 -2
- package/dist/blocks/logo-strip-01/index.js +1 -1
- package/dist/blocks/logo-strip-01/logo-strip.d.ts +1 -1
- package/dist/blocks/logo-strip-01/logo-strip.js +2 -2
- package/dist/blocks/note-grid-01/index.d.ts +2 -2
- package/dist/blocks/note-grid-01/index.js +1 -1
- package/dist/blocks/note-grid-01/note-grid.d.ts +1 -1
- package/dist/blocks/note-grid-01/note-grid.js +1 -1
- package/dist/blocks/page-header-01/index.d.ts +2 -2
- package/dist/blocks/page-header-01/index.js +1 -1
- package/dist/blocks/page-header-01/page-header.d.ts +1 -1
- package/dist/blocks/page-header-01/page-header.js +4 -4
- package/dist/blocks/pricing-01/index.d.ts +1 -1
- package/dist/blocks/pricing-01/index.js +1 -1
- package/dist/blocks/pricing-01/pricing.d.ts +8 -1
- package/dist/blocks/pricing-01/pricing.d.ts.map +1 -1
- package/dist/blocks/pricing-01/pricing.js +15 -5
- package/dist/blocks/process-flow-01/index.d.ts +3 -0
- package/dist/blocks/process-flow-01/index.d.ts.map +1 -0
- package/dist/blocks/process-flow-01/index.js +1 -0
- package/dist/blocks/process-flow-01/process-flow.d.ts +118 -0
- package/dist/blocks/process-flow-01/process-flow.d.ts.map +1 -0
- package/dist/blocks/process-flow-01/process-flow.js +71 -0
- package/dist/blocks/process-rail-01/index.d.ts +2 -2
- package/dist/blocks/process-rail-01/index.js +1 -1
- package/dist/blocks/process-rail-01/process-rail.d.ts +1 -1
- package/dist/blocks/process-rail-01/process-rail.js +2 -2
- package/dist/blocks/product-grid-01/index.d.ts +2 -2
- package/dist/blocks/product-grid-01/index.js +1 -1
- package/dist/blocks/product-grid-01/product-grid.d.ts +37 -5
- package/dist/blocks/product-grid-01/product-grid.d.ts.map +1 -1
- package/dist/blocks/product-grid-01/product-grid.js +20 -6
- package/dist/blocks/run-console-01/index.d.ts +3 -0
- package/dist/blocks/run-console-01/index.d.ts.map +1 -0
- package/dist/blocks/run-console-01/index.js +1 -0
- package/dist/blocks/run-console-01/run-console.d.ts +111 -0
- package/dist/blocks/run-console-01/run-console.d.ts.map +1 -0
- package/dist/blocks/run-console-01/run-console.js +48 -0
- package/dist/blocks/settings-panel-01/index.d.ts +2 -2
- package/dist/blocks/settings-panel-01/index.js +1 -1
- package/dist/blocks/settings-panel-01/settings-panel.d.ts +11 -1
- package/dist/blocks/settings-panel-01/settings-panel.d.ts.map +1 -1
- package/dist/blocks/settings-panel-01/settings-panel.js +15 -10
- package/dist/blocks/site-footer/index.d.ts +2 -2
- package/dist/blocks/site-footer/index.js +1 -1
- package/dist/blocks/site-footer/site-footer.d.ts +1 -1
- package/dist/blocks/site-footer/site-footer.js +2 -2
- package/dist/blocks/site-header/index.d.ts +2 -2
- package/dist/blocks/site-header/index.js +1 -1
- package/dist/blocks/site-header/site-header.d.ts +2 -2
- package/dist/blocks/site-header/site-header.js +3 -3
- package/dist/blocks/site-navbar/index.d.ts +3 -0
- package/dist/blocks/site-navbar/index.d.ts.map +1 -0
- package/dist/blocks/site-navbar/index.js +1 -0
- package/dist/blocks/site-navbar/mobile-nav.d.ts +48 -0
- package/dist/blocks/site-navbar/mobile-nav.d.ts.map +1 -0
- package/dist/blocks/site-navbar/mobile-nav.js +35 -0
- package/dist/blocks/site-navbar/mode-toggle.d.ts +39 -0
- package/dist/blocks/site-navbar/mode-toggle.d.ts.map +1 -0
- package/dist/blocks/site-navbar/mode-toggle.js +39 -0
- package/dist/blocks/site-navbar/navbar-controls.d.ts +79 -0
- package/dist/blocks/site-navbar/navbar-controls.d.ts.map +1 -0
- package/dist/blocks/site-navbar/navbar-controls.js +40 -0
- package/dist/blocks/site-navbar/search-entry.d.ts +29 -0
- package/dist/blocks/site-navbar/search-entry.d.ts.map +1 -0
- package/dist/blocks/site-navbar/search-entry.js +52 -0
- package/dist/blocks/site-navbar/site-navbar.d.ts +212 -0
- package/dist/blocks/site-navbar/site-navbar.d.ts.map +1 -0
- package/dist/blocks/site-navbar/site-navbar.js +61 -0
- package/dist/blocks/site-navbar/sites-menu.d.ts +40 -0
- package/dist/blocks/site-navbar/sites-menu.d.ts.map +1 -0
- package/dist/blocks/site-navbar/sites-menu.js +48 -0
- package/dist/blocks/site-navbar/theme-menu.d.ts +47 -0
- package/dist/blocks/site-navbar/theme-menu.d.ts.map +1 -0
- package/dist/blocks/site-navbar/theme-menu.js +55 -0
- package/dist/blocks/stack-grid-01/index.d.ts +2 -2
- package/dist/blocks/stack-grid-01/index.js +1 -1
- package/dist/blocks/stack-grid-01/stack-grid.d.ts +42 -11
- package/dist/blocks/stack-grid-01/stack-grid.d.ts.map +1 -1
- package/dist/blocks/stack-grid-01/stack-grid.js +15 -7
- package/dist/blocks/stats-01/index.d.ts +9 -1
- package/dist/blocks/stats-01/index.d.ts.map +1 -1
- package/dist/blocks/stats-01/index.js +8 -1
- package/dist/blocks/stats-01/stats.d.ts +1 -1
- package/dist/blocks/stats-01/stats.js +2 -2
- package/dist/blocks/status-ledger-01/index.d.ts +2 -2
- package/dist/blocks/status-ledger-01/index.js +1 -1
- package/dist/blocks/status-ledger-01/status-ledger.d.ts +1 -1
- package/dist/blocks/status-ledger-01/status-ledger.js +2 -2
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +473 -1
- package/dist/components/index.d.ts +104 -66
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +74 -40
- package/dist/components/ui/accordion.js +1 -1
- package/dist/components/ui/alert-dialog.d.ts +119 -0
- package/dist/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/components/ui/alert-dialog.js +82 -0
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/aspect-ratio.d.ts +60 -0
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
- package/dist/components/ui/aspect-ratio.js +61 -0
- package/dist/components/ui/avatar.js +1 -1
- package/dist/components/ui/badge.js +1 -1
- package/dist/components/ui/breadcrumb.js +1 -1
- package/dist/components/ui/button-group.d.ts +68 -0
- package/dist/components/ui/button-group.d.ts.map +1 -0
- package/dist/components/ui/button-group.js +54 -0
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/calendar.d.ts +158 -0
- package/dist/components/ui/calendar.d.ts.map +1 -0
- package/dist/components/ui/calendar.js +216 -0
- package/dist/components/ui/card.d.ts +18 -6
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/card.js +23 -8
- package/dist/components/ui/carousel.d.ts +118 -0
- package/dist/components/ui/carousel.d.ts.map +1 -0
- package/dist/components/ui/carousel.js +152 -0
- package/dist/components/ui/chart-frame.d.ts +216 -0
- package/dist/components/ui/chart-frame.d.ts.map +1 -0
- package/dist/components/ui/chart-frame.js +286 -0
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/collapsible.d.ts +97 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/collapsible.js +54 -0
- package/dist/components/ui/combobox.d.ts +141 -0
- package/dist/components/ui/combobox.d.ts.map +1 -0
- package/dist/components/ui/combobox.js +243 -0
- package/dist/components/ui/command-palette.d.ts +106 -0
- package/dist/components/ui/command-palette.d.ts.map +1 -0
- package/dist/components/ui/command-palette.js +176 -0
- package/dist/components/ui/command.d.ts +82 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/command.js +37 -0
- package/dist/components/ui/context-menu.d.ts +151 -0
- package/dist/components/ui/context-menu.d.ts.map +1 -0
- package/dist/components/ui/context-menu.js +97 -0
- package/dist/components/ui/cta-link.js +1 -1
- package/dist/components/ui/date-picker.d.ts +111 -0
- package/dist/components/ui/date-picker.d.ts.map +1 -0
- package/dist/components/ui/date-picker.js +74 -0
- package/dist/components/ui/diagram.d.ts +84 -15
- package/dist/components/ui/diagram.d.ts.map +1 -1
- package/dist/components/ui/diagram.js +77 -7
- package/dist/components/ui/dialog.js +1 -1
- package/dist/components/ui/diff.d.ts +105 -0
- package/dist/components/ui/diff.d.ts.map +1 -0
- package/dist/components/ui/diff.js +113 -0
- package/dist/components/ui/dropdown-menu.d.ts +18 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu.js +1 -1
- package/dist/components/ui/fact-list.js +1 -1
- package/dist/components/ui/field.js +1 -1
- package/dist/components/ui/form.d.ts +151 -0
- package/dist/components/ui/form.d.ts.map +1 -0
- package/dist/components/ui/form.js +73 -0
- package/dist/components/ui/hover-card.d.ts +105 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/hover-card.js +49 -0
- package/dist/components/ui/input-group.d.ts +99 -0
- package/dist/components/ui/input-group.d.ts.map +1 -0
- package/dist/components/ui/input-group.js +83 -0
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/item.d.ts +113 -0
- package/dist/components/ui/item.d.ts.map +1 -0
- package/dist/components/ui/item.js +61 -0
- package/dist/components/ui/kbd.js +1 -1
- package/dist/components/ui/label.d.ts +58 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +29 -0
- package/dist/components/ui/live-region.d.ts +9 -0
- package/dist/components/ui/live-region.d.ts.map +1 -1
- package/dist/components/ui/live-region.js +10 -2
- package/dist/components/ui/mark.js +1 -1
- package/dist/components/ui/menubar.d.ts +197 -0
- package/dist/components/ui/menubar.d.ts.map +1 -0
- package/dist/components/ui/menubar.js +109 -0
- package/dist/components/ui/meter.d.ts +121 -0
- package/dist/components/ui/meter.d.ts.map +1 -0
- package/dist/components/ui/meter.js +82 -0
- package/dist/components/ui/native-select.d.ts +72 -0
- package/dist/components/ui/native-select.d.ts.map +1 -0
- package/dist/components/ui/native-select.js +55 -0
- package/dist/components/ui/navigation-menu.d.ts +186 -0
- package/dist/components/ui/navigation-menu.d.ts.map +1 -0
- package/dist/components/ui/navigation-menu.js +94 -0
- package/dist/components/ui/number-field.d.ts +111 -0
- package/dist/components/ui/number-field.d.ts.map +1 -0
- package/dist/components/ui/number-field.js +84 -0
- package/dist/components/ui/one-time-code.d.ts +127 -0
- package/dist/components/ui/one-time-code.d.ts.map +1 -0
- package/dist/components/ui/one-time-code.js +57 -0
- package/dist/components/ui/pagination.js +1 -1
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/product-mark.d.ts +1 -1
- package/dist/components/ui/product-mark.js +1 -1
- package/dist/components/ui/product-switcher.d.ts +1 -1
- package/dist/components/ui/product-switcher.js +2 -2
- package/dist/components/ui/progress.js +1 -1
- package/dist/components/ui/prose.js +1 -1
- package/dist/components/ui/pulse-graph.js +1 -1
- package/dist/components/ui/pulse-series.js +1 -1
- package/dist/components/ui/radio-group.js +1 -1
- package/dist/components/ui/resizable.d.ts +129 -0
- package/dist/components/ui/resizable.d.ts.map +1 -0
- package/dist/components/ui/resizable.js +205 -0
- package/dist/components/ui/scroll-area.d.ts +97 -0
- package/dist/components/ui/scroll-area.d.ts.map +1 -0
- package/dist/components/ui/scroll-area.js +68 -0
- package/dist/components/ui/search-dialog.d.ts +139 -0
- package/dist/components/ui/search-dialog.d.ts.map +1 -0
- package/dist/components/ui/search-dialog.js +178 -0
- package/dist/components/ui/section.d.ts +26 -0
- package/dist/components/ui/section.d.ts.map +1 -1
- package/dist/components/ui/section.js +32 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/separator.js +1 -1
- package/dist/components/ui/sheet.d.ts +103 -0
- package/dist/components/ui/sheet.d.ts.map +1 -0
- package/dist/components/ui/sheet.js +58 -0
- package/dist/components/ui/sidebar.d.ts +228 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/sidebar.js +172 -0
- package/dist/components/ui/signal-field.js +1 -1
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/slider.js +1 -1
- package/dist/components/ui/spinner.d.ts +79 -0
- package/dist/components/ui/spinner.d.ts.map +1 -0
- package/dist/components/ui/spinner.js +79 -0
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/table-sort.d.ts +97 -0
- package/dist/components/ui/table-sort.d.ts.map +1 -0
- package/dist/components/ui/table-sort.js +102 -0
- package/dist/components/ui/table.js +1 -1
- package/dist/components/ui/tabs.js +1 -1
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/timeline.d.ts +106 -0
- package/dist/components/ui/timeline.d.ts.map +1 -0
- package/dist/components/ui/timeline.js +111 -0
- package/dist/components/ui/toast.d.ts +219 -0
- package/dist/components/ui/toast.d.ts.map +1 -0
- package/dist/components/ui/toast.js +270 -0
- package/dist/components/ui/toggle-group.d.ts +118 -0
- package/dist/components/ui/toggle-group.d.ts.map +1 -0
- package/dist/components/ui/toggle-group.js +194 -0
- package/dist/components/ui/toggle.d.ts +73 -0
- package/dist/components/ui/toggle.d.ts.map +1 -0
- package/dist/components/ui/toggle.js +44 -0
- package/dist/components/ui/tooltip.js +1 -1
- package/dist/components/ui/tree.js +1 -1
- package/dist/components/ui/typography.js +1 -1
- package/dist/fonts/Inter-OFL.txt +93 -93
- package/dist/index.d.ts +72 -70
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -60
- package/dist/lib/rank.d.ts +69 -0
- package/dist/lib/rank.d.ts.map +1 -0
- package/dist/lib/rank.js +77 -0
- package/dist/live/index.d.ts +22 -0
- package/dist/live/index.d.ts.map +1 -0
- package/dist/live/index.js +20 -0
- package/dist/live/run-stream-01/index.d.ts +3 -0
- package/dist/live/run-stream-01/index.d.ts.map +1 -0
- package/dist/live/run-stream-01/index.js +1 -0
- package/dist/live/run-stream-01/run-stream.d.ts +125 -0
- package/dist/live/run-stream-01/run-stream.d.ts.map +1 -0
- package/dist/live/run-stream-01/run-stream.js +111 -0
- package/dist/pages/auth-page/index.d.ts +15 -2
- package/dist/pages/auth-page/index.d.ts.map +1 -1
- package/dist/pages/auth-page/index.js +8 -4
- package/dist/pages/blog-post-page/index.js +5 -5
- package/dist/pages/dashboard-page/index.d.ts +4 -4
- package/dist/pages/dashboard-page/index.js +4 -4
- package/dist/pages/docs-shell/docs-shell.d.ts +37 -4
- package/dist/pages/docs-shell/docs-shell.d.ts.map +1 -1
- package/dist/pages/docs-shell/docs-shell.js +107 -16
- package/dist/pages/docs-shell/index.d.ts +2 -2
- package/dist/pages/docs-shell/index.js +1 -1
- package/dist/pages/index.d.ts +14 -14
- package/dist/pages/index.js +7 -7
- package/dist/pages/marketing-page/index.d.ts +6 -6
- package/dist/pages/marketing-page/index.js +5 -5
- package/dist/pages/not-found-page/index.js +4 -4
- package/dist/pages/settings-page/index.d.ts +3 -3
- package/dist/pages/settings-page/index.js +4 -4
- package/dist/provider/index.d.ts +4 -4
- package/dist/provider/index.js +2 -2
- package/dist/provider/provider.d.ts +1 -1
- package/dist/provider/provider.js +1 -1
- package/dist/provider/theme-script.d.ts +1 -1
- package/dist/provider/theme-script.js +1 -1
- package/dist/styles.css +689 -0
- package/package.json +9 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { type CalendarWeekdays } from './calendar.js';
|
|
2
|
+
/** The props the Date picker accepts. */
|
|
3
|
+
export interface DatePickerProps {
|
|
4
|
+
/**
|
|
5
|
+
* The accessible name of the field.
|
|
6
|
+
*
|
|
7
|
+
* Required. It is rendered as the field's own name rather than as visible text,
|
|
8
|
+
* because a visible label belongs above the control and that is the caller's
|
|
9
|
+
* `Label` to place. What the Component owns is the name, and a field with no
|
|
10
|
+
* name is a field a screen reader reader cannot say out loud.
|
|
11
|
+
*/
|
|
12
|
+
label: string;
|
|
13
|
+
/**
|
|
14
|
+
* Formats a chosen date for the field.
|
|
15
|
+
*
|
|
16
|
+
* Required, and required as a function rather than as a format string, because a
|
|
17
|
+
* date is a phrase in the reader's language and their convention. This Component
|
|
18
|
+
* ships no date format: a hardcoded one would be a claim about how dates are
|
|
19
|
+
* written in every consumer's product.
|
|
20
|
+
*/
|
|
21
|
+
format: (date: Date) => string;
|
|
22
|
+
/** The caption for a month on show, in the reader's language. */
|
|
23
|
+
monthLabel: (month: Date) => string;
|
|
24
|
+
/** The seven weekday headings, starting from `firstWeekday`. */
|
|
25
|
+
weekdayLabels: CalendarWeekdays;
|
|
26
|
+
/** Which day the reader's week starts on, as `Date.prototype.getDay()` numbers it. */
|
|
27
|
+
firstWeekday?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
28
|
+
/** The accessible name of the control that steps back one month. */
|
|
29
|
+
previousLabel: string;
|
|
30
|
+
/** The accessible name of the control that steps forward one month. */
|
|
31
|
+
nextLabel: string;
|
|
32
|
+
/**
|
|
33
|
+
* The accessible name of the control that clears the field.
|
|
34
|
+
*
|
|
35
|
+
* Omit it and the control is not rendered. The words are the caller's because
|
|
36
|
+
* they are a sentence a reader hears, and a Component that chose them would be
|
|
37
|
+
* shipping English into every consumer's form.
|
|
38
|
+
*/
|
|
39
|
+
clearLabel?: string;
|
|
40
|
+
/**
|
|
41
|
+
* What the field shows before a date is chosen.
|
|
42
|
+
*
|
|
43
|
+
* Hidden from the accessibility tree, because the field already has a name and
|
|
44
|
+
* a placeholder that becomes a second name is a field announced twice.
|
|
45
|
+
*/
|
|
46
|
+
placeholder?: string;
|
|
47
|
+
/** The chosen date, when the field is controlled. */
|
|
48
|
+
value?: Date | null;
|
|
49
|
+
/** The date chosen initially, for an uncontrolled field. */
|
|
50
|
+
defaultValue?: Date | null;
|
|
51
|
+
/** Called with the chosen date, or `null` when the reader clears the field. */
|
|
52
|
+
onValueChange?: (date: Date | null) => void;
|
|
53
|
+
/** Whether a date cannot be chosen. */
|
|
54
|
+
isDateDisabled?: (date: Date) => boolean;
|
|
55
|
+
/** The full accessible name of a day, in the reader's own date format. */
|
|
56
|
+
dayLabel?: (date: Date) => string;
|
|
57
|
+
/** The date to mark as today. Defaults to the reader's clock. */
|
|
58
|
+
today?: Date;
|
|
59
|
+
/** Whether the reader may not open the calendar or choose a date. */
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
/** Whether a date must be chosen before the form submits. */
|
|
62
|
+
required?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* The form field name. The chosen date is submitted as `YYYY-MM-DD`.
|
|
65
|
+
*
|
|
66
|
+
* Never the displayed string. A form that posts whatever the reader's locale
|
|
67
|
+
* wrote makes every reader of that data parse a phrase.
|
|
68
|
+
*/
|
|
69
|
+
name?: string;
|
|
70
|
+
/** Identifies the form that owns the hidden input. */
|
|
71
|
+
form?: string;
|
|
72
|
+
/** The field's own id, so a label elsewhere can point at it. */
|
|
73
|
+
id?: string;
|
|
74
|
+
/** Layout only. */
|
|
75
|
+
className?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A field that opens a month grid and holds the date the reader picks.
|
|
79
|
+
*
|
|
80
|
+
* **It is built on the Calendar rather than beside it.** The month grid is a
|
|
81
|
+
* month grid: six rows, a roving tab stop, arrow keys that cross into the next
|
|
82
|
+
* month, and a rule about what a disabled date means. A picker with its own grid
|
|
83
|
+
* would be a second answer to all six questions, and the second answer is the one
|
|
84
|
+
* that ships the bug.
|
|
85
|
+
*
|
|
86
|
+
* **Choosing a date commits it and closes, in one gesture.** A field that left the
|
|
87
|
+
* grid open after a choice asks the reader to confirm an answer they already gave,
|
|
88
|
+
* and the Popover returns focus to the trigger on close, so a reader who is
|
|
89
|
+
* tabbing onward from the field is where they expect to be rather than back at
|
|
90
|
+
* the top of the document.
|
|
91
|
+
*
|
|
92
|
+
* **The month on show follows the answer, every time the field is opened.** A
|
|
93
|
+
* filled field opens on the month of its value, and an empty one on the current
|
|
94
|
+
* month. Without this, re-picking a date in a different month would reset the grid
|
|
95
|
+
* to the month the caller seeded it with, which is the month the reader was in
|
|
96
|
+
* the first time and is a silent undo of the navigation they just did.
|
|
97
|
+
*
|
|
98
|
+
* **The field shows the caller's formatted date and submits an ISO day.** Those are
|
|
99
|
+
* two different strings on purpose: one is read by a person and written in their
|
|
100
|
+
* language, the other is read by a machine that has no locale. A field that
|
|
101
|
+
* submitted what it displayed hands every downstream reader a phrase to parse.
|
|
102
|
+
*
|
|
103
|
+
* **The name and the value are announced separately.** The name is the field's
|
|
104
|
+
* label and the value is its description, which is how a field is read: "Delivery
|
|
105
|
+
* date, 17 March 2026". Letting the visible date become the button's name would
|
|
106
|
+
* replace the field's name with its current answer, so a reader who tabs through
|
|
107
|
+
* a form of five date fields hears five dates and no questions.
|
|
108
|
+
*/
|
|
109
|
+
declare function DatePicker({ label, format, monthLabel, weekdayLabels, firstWeekday, previousLabel, nextLabel, clearLabel, placeholder, value, defaultValue, onValueChange, isDateDisabled, dayLabel, today, disabled, required, name, form, id, className, }: DatePickerProps): import("react").JSX.Element;
|
|
110
|
+
export { DatePicker };
|
|
111
|
+
//# sourceMappingURL=date-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../../../src/components/ui/date-picker.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAY,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAI5D,yCAAyC;AACzC,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;OAOG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IAC9B,iEAAiE;IACjE,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,MAAM,CAAA;IACnC,gEAAgE;IAChE,aAAa,EAAE,gBAAgB,CAAA;IAC/B,sFAAsF;IACtF,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACxC,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qDAAqD;IACrD,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IACnB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IAC1B,+EAA+E;IAC/E,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAA;IAC3C,uCAAuC;IACvC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAA;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IACjC,iEAAiE;IACjE,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,mBAAmB;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,iBAAS,UAAU,CAAC,EAClB,KAAK,EACL,MAAM,EACN,UAAU,EACV,aAAa,EACb,YAAgB,EAChB,aAAa,EACb,SAAS,EACT,UAAU,EACV,WAAW,EACX,KAAK,EACL,YAAmB,EACnB,aAAa,EACb,cAAc,EACd,QAAQ,EACR,KAAkB,EAClB,QAAgB,EAChB,QAAgB,EAChB,IAAI,EACJ,IAAI,EACJ,EAAE,EACF,SAAS,GACV,EAAE,eAAe,+BA0HjB;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { XIcon } from 'lucide-react';
|
|
4
|
+
import { useCallback, useId, useState } from 'react';
|
|
5
|
+
import { Calendar } from './calendar.js';
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
|
|
7
|
+
import { cn } from '../../lib/utils.js';
|
|
8
|
+
/** `YYYY-MM-DD`, which is the only date format a form should post. */
|
|
9
|
+
const iso = (date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
|
10
|
+
const startOfMonth = (date) => new Date(date.getFullYear(), date.getMonth(), 1);
|
|
11
|
+
/**
|
|
12
|
+
* A field that opens a month grid and holds the date the reader picks.
|
|
13
|
+
*
|
|
14
|
+
* **It is built on the Calendar rather than beside it.** The month grid is a
|
|
15
|
+
* month grid: six rows, a roving tab stop, arrow keys that cross into the next
|
|
16
|
+
* month, and a rule about what a disabled date means. A picker with its own grid
|
|
17
|
+
* would be a second answer to all six questions, and the second answer is the one
|
|
18
|
+
* that ships the bug.
|
|
19
|
+
*
|
|
20
|
+
* **Choosing a date commits it and closes, in one gesture.** A field that left the
|
|
21
|
+
* grid open after a choice asks the reader to confirm an answer they already gave,
|
|
22
|
+
* and the Popover returns focus to the trigger on close, so a reader who is
|
|
23
|
+
* tabbing onward from the field is where they expect to be rather than back at
|
|
24
|
+
* the top of the document.
|
|
25
|
+
*
|
|
26
|
+
* **The month on show follows the answer, every time the field is opened.** A
|
|
27
|
+
* filled field opens on the month of its value, and an empty one on the current
|
|
28
|
+
* month. Without this, re-picking a date in a different month would reset the grid
|
|
29
|
+
* to the month the caller seeded it with, which is the month the reader was in
|
|
30
|
+
* the first time and is a silent undo of the navigation they just did.
|
|
31
|
+
*
|
|
32
|
+
* **The field shows the caller's formatted date and submits an ISO day.** Those are
|
|
33
|
+
* two different strings on purpose: one is read by a person and written in their
|
|
34
|
+
* language, the other is read by a machine that has no locale. A field that
|
|
35
|
+
* submitted what it displayed hands every downstream reader a phrase to parse.
|
|
36
|
+
*
|
|
37
|
+
* **The name and the value are announced separately.** The name is the field's
|
|
38
|
+
* label and the value is its description, which is how a field is read: "Delivery
|
|
39
|
+
* date, 17 March 2026". Letting the visible date become the button's name would
|
|
40
|
+
* replace the field's name with its current answer, so a reader who tabs through
|
|
41
|
+
* a form of five date fields hears five dates and no questions.
|
|
42
|
+
*/
|
|
43
|
+
function DatePicker({ label, format, monthLabel, weekdayLabels, firstWeekday = 0, previousLabel, nextLabel, clearLabel, placeholder, value, defaultValue = null, onValueChange, isDateDisabled, dayLabel, today = new Date(), disabled = false, required = false, name, form, id, className, }) {
|
|
44
|
+
const [ownValue, setOwnValue] = useState(defaultValue);
|
|
45
|
+
const [ownOpen, setOwnOpen] = useState(false);
|
|
46
|
+
const [month, setMonth] = useState(() => startOfMonth(defaultValue ?? today));
|
|
47
|
+
const generated = useId();
|
|
48
|
+
const triggerId = id ?? generated;
|
|
49
|
+
const valueId = `${generated}-value`;
|
|
50
|
+
const chosen = value === undefined ? ownValue : value;
|
|
51
|
+
const open = ownOpen;
|
|
52
|
+
const shown = chosen === null ? '' : format(chosen);
|
|
53
|
+
const choose = (date) => {
|
|
54
|
+
if (value === undefined)
|
|
55
|
+
setOwnValue(date);
|
|
56
|
+
onValueChange?.(date);
|
|
57
|
+
setOwnOpen(false);
|
|
58
|
+
};
|
|
59
|
+
const clear = useCallback(() => {
|
|
60
|
+
if (value === undefined)
|
|
61
|
+
setOwnValue(null);
|
|
62
|
+
onValueChange?.(null);
|
|
63
|
+
}, [onValueChange, value]);
|
|
64
|
+
const onOpenChange = (next) => {
|
|
65
|
+
// Reseeded on every open rather than held, so the grid always arrives on the
|
|
66
|
+
// month the reader is about to edit.
|
|
67
|
+
if (next)
|
|
68
|
+
setMonth(startOfMonth(chosen ?? today));
|
|
69
|
+
setOwnOpen(next);
|
|
70
|
+
};
|
|
71
|
+
const canClear = chosen !== null && clearLabel !== undefined;
|
|
72
|
+
return (_jsxs("div", { "data-slot": "date-picker", className: cn('relative w-full', className), children: [canClear ? (_jsx("button", { type: "button", "data-slot": "date-picker-clear", "aria-label": clearLabel, disabled: disabled, onClick: clear, className: cn('text-muted-foreground hover:text-foreground absolute top-1/2 right-9 z-10 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-sm outline-none', 'transition-colors duration-fast ease-out focus-visible:ring-ring focus-visible:ring-[3px]', 'disabled:pointer-events-none disabled:opacity-50'), children: _jsx(XIcon, { className: "size-4", "aria-hidden": "true" }) })) : null, _jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { "data-slot": "date-picker-trigger", id: triggerId, "aria-label": label, "aria-describedby": shown === '' ? undefined : valueId, "aria-invalid": required && chosen === null ? true : undefined, disabled: disabled, className: cn('border-input bg-background text-foreground w-full justify-between outline-none', 'focus-visible:border-ring focus-visible:ring-ring focus-visible:ring-[3px]', canClear && 'pr-16'), children: _jsx("span", { "data-slot": "date-picker-value", "aria-hidden": "true", className: shown === '' ? 'text-muted-foreground' : undefined, children: shown === '' ? placeholder : shown }) }), _jsx(PopoverContent, { sideOffset: 4, "aria-label": label, className: "w-auto p-0", children: _jsx(Calendar, { label: label, monthLabel: monthLabel(month), weekdayLabels: weekdayLabels, firstWeekday: firstWeekday, previousLabel: previousLabel, nextLabel: nextLabel, month: month, onMonthChange: setMonth, value: chosen, onValueChange: choose, isDateDisabled: isDateDisabled, dayLabel: dayLabel, today: today }) })] }), shown === '' ? null : (_jsx("span", { id: valueId, className: "sr-only", children: shown })), name === undefined ? null : (_jsx("input", { type: "hidden", name: name, ...(form === undefined ? null : { form }), value: chosen === null ? '' : iso(chosen), readOnly: true }))] }));
|
|
73
|
+
}
|
|
74
|
+
export { DatePicker };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PackId } from '../../theming/index.js';
|
|
1
2
|
/**
|
|
2
3
|
* One named thing in a Diagram, at a position the caller chooses.
|
|
3
4
|
*
|
|
@@ -7,11 +8,12 @@
|
|
|
7
8
|
* another, so a caller that means a column spreads it rather than repeating a
|
|
8
9
|
* number.
|
|
9
10
|
*
|
|
10
|
-
* `emphasis` marks the one node the
|
|
11
|
-
*
|
|
12
|
-
* DESIGN.md's Brand Ink Rule names as the colour for something
|
|
13
|
-
* as the brand rather than as body text
|
|
14
|
-
* mistake, not a second emphasis level.
|
|
11
|
+
* A node carries two differences and no more. `emphasis` marks the one node the
|
|
12
|
+
* drawing is about, and it is the emphasised node that takes the brand ink,
|
|
13
|
+
* which is what DESIGN.md's Brand Ink Rule names as the colour for something
|
|
14
|
+
* that must read as the brand rather than as body text; two emphasised nodes are
|
|
15
|
+
* a caller's mistake, not a second emphasis level. `pack` is the node's own hue,
|
|
16
|
+
* and it is per node for the reasons given on that field.
|
|
15
17
|
*/
|
|
16
18
|
export type DiagramNode = {
|
|
17
19
|
/**
|
|
@@ -25,12 +27,48 @@ export type DiagramNode = {
|
|
|
25
27
|
* reader does not read it: see `DiagramProps` for what carries the meaning.
|
|
26
28
|
*/
|
|
27
29
|
name: string;
|
|
30
|
+
/**
|
|
31
|
+
* The second line printed under the name, which is the one-line role the thing
|
|
32
|
+
* plays: "the shared language", "the engine", "built next".
|
|
33
|
+
*
|
|
34
|
+
* It is a field rather than a word written into `label`, because the two
|
|
35
|
+
* audiences are different and a role description that exists only inside the
|
|
36
|
+
* accessible name has been given to one of them and withheld from the other.
|
|
37
|
+
* It is drawn on the picture, it is read aloud as part of the name when the
|
|
38
|
+
* caller passes no `label`, and because both come out of the same field they
|
|
39
|
+
* are the same words and cannot drift.
|
|
40
|
+
*/
|
|
41
|
+
subtitle?: string;
|
|
28
42
|
/** The node's position along the horizontal axis, in the caller's space. */
|
|
29
43
|
x: number;
|
|
30
44
|
/** The node's position along the vertical axis, in the caller's space. */
|
|
31
45
|
y: number;
|
|
32
46
|
/** Marks the node the diagram is about. See the Brand Ink Rule. */
|
|
33
47
|
emphasis?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* The node's pack, which is the hue its mark wears.
|
|
50
|
+
*
|
|
51
|
+
* `PackId` rather than `string`, because a pack is one of the six published
|
|
52
|
+
* packs: a free-text field would accept a name matching no emitted rule, and a
|
|
53
|
+
* mark under a boundary nothing matches keeps the colour of whatever pack is
|
|
54
|
+
* above it, which is a silent wrong answer rather than a rejected one.
|
|
55
|
+
*
|
|
56
|
+
* **It is per node, and that is settled rather than incidental.** A pack on
|
|
57
|
+
* the Diagram would be one boundary on the section, and the boundary is the
|
|
58
|
+
* unit of a second pack on a MARK: `ProductMark` is the item that established
|
|
59
|
+
* it, and a mark here is a node. Per node is also what a schematic wants. One
|
|
60
|
+
* drawing of a product set shows one mark per product and each wears its own
|
|
61
|
+
* hue, which a single boundary could not express at all.
|
|
62
|
+
*
|
|
63
|
+
* The boundary lands on the `<circle>` this node draws, and not on the `<svg>`
|
|
64
|
+
* and not on the node's `<g>`, so it moves that one mark's fill and stroke and
|
|
65
|
+
* nothing else. A circle has no radius concept, so the pack re-inks the mark
|
|
66
|
+
* and cannot re-round it, which is the half of the pack boundary law a
|
|
67
|
+
* consumer implementing only the colour half gets wrong. `default` is the
|
|
68
|
+
* absence of the attribute, exactly as `themeAttributes` spells it, so a node
|
|
69
|
+
* on the base pack carries no `data-pack` and resolves from the page.
|
|
70
|
+
*/
|
|
71
|
+
pack?: PackId;
|
|
34
72
|
};
|
|
35
73
|
/**
|
|
36
74
|
* One relation between two nodes, with the word that says what it is.
|
|
@@ -55,7 +93,7 @@ export type DiagramRelation = {
|
|
|
55
93
|
/** Draws the line dashed, for a relation that holds but not by this route. */
|
|
56
94
|
indirect?: boolean;
|
|
57
95
|
};
|
|
58
|
-
/** What
|
|
96
|
+
/** What every arm of `DiagramProps` carries. */
|
|
59
97
|
type DiagramFigure = {
|
|
60
98
|
/** The things drawn. At least one, or the Diagram renders an empty canvas. */
|
|
61
99
|
nodes: readonly DiagramNode[];
|
|
@@ -71,11 +109,18 @@ type DiagramFigure = {
|
|
|
71
109
|
/**
|
|
72
110
|
* The props a Diagram takes.
|
|
73
111
|
*
|
|
74
|
-
* The name is required unless the drawing is decorative
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
112
|
+
* The name is required unless the drawing is decorative or the nodes can be read
|
|
113
|
+
* as the name, and it is forbidden when the drawing is decorative. That is a
|
|
114
|
+
* union rather than `label?: string` because only a union lets the type system
|
|
115
|
+
* see the exception: an optional label on one type can only be optional
|
|
116
|
+
* everywhere or required everywhere, and both halves of that are wrong.
|
|
117
|
+
* `Separator` takes the same shape as `decorative`.
|
|
118
|
+
*
|
|
119
|
+
* The third arm is the one that makes the name derivable. It spells the absence
|
|
120
|
+
* as `label?: never` rather than `label?: string`, so "the caller named it" and
|
|
121
|
+
* "the caller passed nothing" cannot be confused for one another and a caller
|
|
122
|
+
* cannot hand the drawing an empty name by passing one: an unnamed image is the
|
|
123
|
+
* one outcome this prop must not have.
|
|
79
124
|
*/
|
|
80
125
|
export type DiagramProps = DiagramFigure & ({
|
|
81
126
|
/**
|
|
@@ -90,6 +135,16 @@ export type DiagramProps = DiagramFigure & ({
|
|
|
90
135
|
/** The name of the drawing, and the only thing a screen reader reads from it. */
|
|
91
136
|
label: string;
|
|
92
137
|
decorative?: false;
|
|
138
|
+
} | {
|
|
139
|
+
/**
|
|
140
|
+
* No name is passed, so the drawing is named by what its own marks say:
|
|
141
|
+
* every node's `name`, and its `subtitle` where it has one, in the order
|
|
142
|
+
* the caller drew them. A caller who gives a node a role description is
|
|
143
|
+
* describing the picture, and a picture's own words are the honest source
|
|
144
|
+
* for the name announced over it.
|
|
145
|
+
*/
|
|
146
|
+
label?: never;
|
|
147
|
+
decorative?: false;
|
|
93
148
|
});
|
|
94
149
|
/**
|
|
95
150
|
* A diagram of named things and the relations between them.
|
|
@@ -107,13 +162,27 @@ export type DiagramProps = DiagramFigure & ({
|
|
|
107
162
|
* roster, and a `'use client'` line added here would put it back on that roster.
|
|
108
163
|
*
|
|
109
164
|
* **Accessibility.** A diagram carries meaning, so by default it is one image
|
|
110
|
-
* with a name: `role="img"` and the
|
|
111
|
-
*
|
|
112
|
-
* drawn for sighted readers and the
|
|
113
|
-
* gets.
|
|
165
|
+
* with a name: `role="img"` and the drawing's name. Everything inside a
|
|
166
|
+
* `role="img"` is presentational, so the node names, the node subtitles and the
|
|
167
|
+
* relation words are drawn for sighted readers and the name is what a screen
|
|
168
|
+
* reader gets. That is why the name is derived from the nodes' own text when the
|
|
169
|
+
* caller passes no `label`: everything on the marks is invisible to the one
|
|
170
|
+
* reader who is not looking at the picture, so a role description written only
|
|
171
|
+
* into a label is a role description a sighted reader never sees. Pass `label`
|
|
172
|
+
* when the drawing needs a name that says what it is rather than what it holds,
|
|
173
|
+
* and omit it when the two would be the same sentence written twice. Pass
|
|
174
|
+
* `decorative` when the surrounding sentence already says what the drawing
|
|
114
175
|
* shows, and the whole tree leaves the accessibility tree with nothing named
|
|
115
176
|
* inside it.
|
|
116
177
|
*
|
|
178
|
+
* **A node may wear its own pack.** `pack` on a node puts the boundary on the
|
|
179
|
+
* circle that node draws, which is the mark, and the mark is the one place a
|
|
180
|
+
* pack boundary belongs without moving anything but colour: a circle has no
|
|
181
|
+
* radius concept, so the pack re-inks the mark and cannot re-round it. Nothing
|
|
182
|
+
* else in the drawing answers to it, the node's name beside the mark keeps the
|
|
183
|
+
* page's ink, and a page that files two pack regions can make a diagram section
|
|
184
|
+
* the second one rather than moving it to the header's product switcher.
|
|
185
|
+
*
|
|
117
186
|
* **Shape.** Nodes are circles and relations are paths. Both are shapes with no
|
|
118
187
|
* radius concept, so no corner radius here is a function of `--radius` and a
|
|
119
188
|
* pack boundary above the drawing moves nothing about its shape. A `<rect>` was
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagram.d.ts","sourceRoot":"","sources":["../../../src/components/ui/diagram.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"diagram.d.ts","sourceRoot":"","sources":["../../../src/components/ui/diagram.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAI3C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAA;IACV;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,CAAC,EAAE,MAAM,CAAA;IACT,0EAA0E;IAC1E,CAAC,EAAE,MAAM,CAAA;IACT,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAA;IACZ,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAA;IACV,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,gDAAgD;AAChD,KAAK,aAAa,GAAG;IACnB,8EAA8E;IAC9E,KAAK,EAAE,SAAS,WAAW,EAAE,CAAA;IAC7B,oGAAoG;IACpG,SAAS,EAAE,SAAS,eAAe,EAAE,CAAA;IACrC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,YAAY,GAAG,aAAa,GACtC,CACI;IACE;;;;;OAKG;IACH,UAAU,EAAE,IAAI,CAAA;IAChB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GACD;IACE,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,GACD;IACE;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,CACJ,CAAA;AAiIH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,iBAAS,OAAO,CAAC,EACf,KAAK,EACL,SAAS,EACT,KAAK,EACL,UAAkB,EAClB,SAAS,GACV,EAAE,YAAY,+BAgHd;AAED,OAAO,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { cn } from '../../lib/utils';
|
|
2
|
+
import { cn } from '../../lib/utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* The drawing's accessible name, derived from the text its own marks carry.
|
|
5
|
+
*
|
|
6
|
+
* Derived rather than passed because the two audiences are different and a
|
|
7
|
+
* Component able to reach only one of them reaches neither. Everything inside a
|
|
8
|
+
* `role="img"` is presentational, so the words drawn on the marks are words no
|
|
9
|
+
* screen reader reads, and the label is the one thing it does read. A caller who
|
|
10
|
+
* put a node's role description into the label and not onto the node had
|
|
11
|
+
* published half of it: the half a sighted reader loses. Reading the name off the
|
|
12
|
+
* marks is what makes that drift impossible rather than merely discouraged, and
|
|
13
|
+
* it is why the drawn line and the announced line are the same field.
|
|
14
|
+
*
|
|
15
|
+
* Relation words are not part of it, and that is the honest limit of a
|
|
16
|
+
* derivation rather than an oversight. A derived name says what the drawing
|
|
17
|
+
* holds; a caller whose relations matter to a screen reader user passes a
|
|
18
|
+
* `label` that says so. Inventing a sentence out of the relations would be this
|
|
19
|
+
* Component writing the words, which is the one thing it does not do.
|
|
20
|
+
*/
|
|
21
|
+
function derivedName(nodes) {
|
|
22
|
+
return nodes.reduce((name, node) => {
|
|
23
|
+
// Parentheses between a thing and its role, commas between things, so a
|
|
24
|
+
// reader hearing the list can tell which words belong to which mark. Both
|
|
25
|
+
// are punctuation assembled here rather than a word this Component wrote.
|
|
26
|
+
const words = node.subtitle ? `${node.name} (${node.subtitle})` : node.name;
|
|
27
|
+
return name === '' ? words : `${name}, ${words}`;
|
|
28
|
+
}, '');
|
|
29
|
+
}
|
|
3
30
|
/**
|
|
4
31
|
* The canvas the Diagram draws into, in its own user units.
|
|
5
32
|
*
|
|
@@ -21,6 +48,12 @@ const CANVAS_HEIGHT = 400;
|
|
|
21
48
|
* and a name is wider than the mark. The band is the honest cost of a server
|
|
22
49
|
* component not being able to measure text, and it is why a name that runs long
|
|
23
50
|
* still lands inside the canvas rather than off its edge.
|
|
51
|
+
*
|
|
52
|
+
* A node's subtitle, where it has one, is the deepest ink a node draws, at
|
|
53
|
+
* `NODE_SUBTITLE_OFFSET` below the mark, and that is inside the band too. The
|
|
54
|
+
* cost of not being able to measure text is paid once rather than per line, and
|
|
55
|
+
* paying it for the second line is what keeps the two-line node inside the
|
|
56
|
+
* canvas rather than under its own floor.
|
|
24
57
|
*/
|
|
25
58
|
const PADDING = 56;
|
|
26
59
|
/** The node mark's radius. A circle, so there is no corner radius for the pack to move. */
|
|
@@ -35,7 +68,17 @@ const NODE_RADIUS = 5;
|
|
|
35
68
|
*/
|
|
36
69
|
const NODE_NAME_SIZE = 13;
|
|
37
70
|
const NODE_NAME_OFFSET = 20;
|
|
71
|
+
const NODE_SUBTITLE_SIZE = 11;
|
|
38
72
|
const RELATION_NAME_SIZE = 11;
|
|
73
|
+
/**
|
|
74
|
+
* The subtitle's baseline, measured down from the mark's centre.
|
|
75
|
+
*
|
|
76
|
+
* The name's baseline, then the subtitle's own size, then a line of leading. It is
|
|
77
|
+
* the deepest any node draws and it is why `PADDING` has to be what it is; a
|
|
78
|
+
* second line that were placed on the name rather than below it would collide
|
|
79
|
+
* with it on every node that had one.
|
|
80
|
+
*/
|
|
81
|
+
const NODE_SUBTITLE_OFFSET = NODE_NAME_OFFSET + NODE_SUBTITLE_SIZE + 5;
|
|
39
82
|
/**
|
|
40
83
|
* How far a relation's label sits off its line, in user units. Perpendicular to
|
|
41
84
|
* the line, so the label never sits on the stroke it belongs to.
|
|
@@ -83,13 +126,27 @@ function fit(nodes) {
|
|
|
83
126
|
* roster, and a `'use client'` line added here would put it back on that roster.
|
|
84
127
|
*
|
|
85
128
|
* **Accessibility.** A diagram carries meaning, so by default it is one image
|
|
86
|
-
* with a name: `role="img"` and the
|
|
87
|
-
*
|
|
88
|
-
* drawn for sighted readers and the
|
|
89
|
-
* gets.
|
|
129
|
+
* with a name: `role="img"` and the drawing's name. Everything inside a
|
|
130
|
+
* `role="img"` is presentational, so the node names, the node subtitles and the
|
|
131
|
+
* relation words are drawn for sighted readers and the name is what a screen
|
|
132
|
+
* reader gets. That is why the name is derived from the nodes' own text when the
|
|
133
|
+
* caller passes no `label`: everything on the marks is invisible to the one
|
|
134
|
+
* reader who is not looking at the picture, so a role description written only
|
|
135
|
+
* into a label is a role description a sighted reader never sees. Pass `label`
|
|
136
|
+
* when the drawing needs a name that says what it is rather than what it holds,
|
|
137
|
+
* and omit it when the two would be the same sentence written twice. Pass
|
|
138
|
+
* `decorative` when the surrounding sentence already says what the drawing
|
|
90
139
|
* shows, and the whole tree leaves the accessibility tree with nothing named
|
|
91
140
|
* inside it.
|
|
92
141
|
*
|
|
142
|
+
* **A node may wear its own pack.** `pack` on a node puts the boundary on the
|
|
143
|
+
* circle that node draws, which is the mark, and the mark is the one place a
|
|
144
|
+
* pack boundary belongs without moving anything but colour: a circle has no
|
|
145
|
+
* radius concept, so the pack re-inks the mark and cannot re-round it. Nothing
|
|
146
|
+
* else in the drawing answers to it, the node's name beside the mark keeps the
|
|
147
|
+
* page's ink, and a page that files two pack regions can make a diagram section
|
|
148
|
+
* the second one rather than moving it to the header's product switcher.
|
|
149
|
+
*
|
|
93
150
|
* **Shape.** Nodes are circles and relations are paths. Both are shapes with no
|
|
94
151
|
* radius concept, so no corner radius here is a function of `--radius` and a
|
|
95
152
|
* pack boundary above the drawing moves nothing about its shape. A `<rect>` was
|
|
@@ -128,12 +185,17 @@ function fit(nodes) {
|
|
|
128
185
|
function Diagram({ nodes, relations, label, decorative = false, className, }) {
|
|
129
186
|
const place = fit(nodes);
|
|
130
187
|
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
188
|
+
// An empty `label` is the same answer as no `label`, so the drawing is named by
|
|
189
|
+
// what its own marks carry rather than announced as an unnamed image. A blank
|
|
190
|
+
// string is the one value the accessible name must never take, and the caller
|
|
191
|
+
// who passed it has said no more than the caller who passed nothing.
|
|
192
|
+
const name = label !== undefined && label.trim() !== '' ? label : derivedName(nodes);
|
|
131
193
|
const drawn = relations.flatMap((relation) => {
|
|
132
194
|
const from = byId.get(relation.from);
|
|
133
195
|
const to = byId.get(relation.to);
|
|
134
196
|
return from && to ? [{ relation, from: place(from), to: place(to) }] : [];
|
|
135
197
|
});
|
|
136
|
-
return (_jsxs("svg", { "data-slot": "diagram", "data-unresolved-relations": relations.length - drawn.length, viewBox: `0 0 ${CANVAS_WIDTH} ${CANVAS_HEIGHT}`, xmlns: "http://www.w3.org/2000/svg", role: decorative ? undefined : 'img', "aria-label": decorative ? undefined :
|
|
198
|
+
return (_jsxs("svg", { "data-slot": "diagram", "data-unresolved-relations": relations.length - drawn.length, viewBox: `0 0 ${CANVAS_WIDTH} ${CANVAS_HEIGHT}`, xmlns: "http://www.w3.org/2000/svg", role: decorative ? undefined : 'img', "aria-label": decorative ? undefined : name, "aria-hidden": decorative || undefined, className: cn('h-auto w-full', className), children: [drawn.map(({ relation, from, to }) => {
|
|
137
199
|
// A label placed beside its line rather than on it. The offset is the
|
|
138
200
|
// line's normal, so a vertical relation's label sits beside it and a
|
|
139
201
|
// horizontal one's sits above it, and neither ever sits on the stroke.
|
|
@@ -144,7 +206,15 @@ function Diagram({ nodes, relations, label, decorative = false, className, }) {
|
|
|
144
206
|
return (_jsxs("g", { "data-slot": "diagram-relation", "data-relation": `${relation.from}-${relation.to}`, children: [_jsx("path", { d: `M ${from.x} ${from.y} L ${to.x} ${to.y}`, strokeWidth: 1, strokeDasharray: relation.indirect ? '4 4' : undefined, className: "stroke-muted-foreground fill-none" }), _jsx("text", { x: (from.x + to.x) / 2 - dy * lift, y: (from.y + to.y) / 2 + dx * lift, fontSize: RELATION_NAME_SIZE, textAnchor: "middle", className: "fill-muted-foreground font-mono", children: relation.label })] }, `${relation.from}-${relation.to}`));
|
|
145
207
|
}), nodes.map((node) => {
|
|
146
208
|
const at = place(node);
|
|
147
|
-
|
|
209
|
+
// `default` is the absence of the attribute, spelled the way the token
|
|
210
|
+
// build spells it, so a node on the base pack resolves its fill and its
|
|
211
|
+
// stroke from the page rather than from a selector nothing emits.
|
|
212
|
+
const boundary = node.pack !== undefined && node.pack !== 'default' ? node.pack : undefined;
|
|
213
|
+
return (_jsxs("g", { "data-slot": "diagram-node", "data-node": node.id, "data-emphasis": node.emphasis || undefined, children: [_jsx("circle", { cx: at.x, cy: at.y, r: NODE_RADIUS, "data-pack": boundary, strokeWidth: node.emphasis ? 2 : 1, className: cn(node.emphasis ? 'fill-accent stroke-brand-ink' : 'fill-card stroke-border') }), _jsx("text", { x: at.x, y: at.y + NODE_NAME_OFFSET, fontSize: NODE_NAME_SIZE, textAnchor: "middle", className: "fill-foreground font-mono", children: node.name }), node.subtitle ? (_jsx("text", { "data-slot": "diagram-node-subtitle", x: at.x, y: at.y + NODE_SUBTITLE_OFFSET, fontSize: NODE_SUBTITLE_SIZE, textAnchor: "middle",
|
|
214
|
+
// Muted ink rather than the name's own: the line below a name is
|
|
215
|
+
// supporting, and a reader's eye reaches the name first. Both are
|
|
216
|
+
// contract roles, so a boundary above either moves it.
|
|
217
|
+
className: "fill-muted-foreground font-mono", children: node.subtitle })) : null] }, node.id));
|
|
148
218
|
})] }));
|
|
149
219
|
}
|
|
150
220
|
export { Diagram };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
|
|
4
4
|
import { XIcon } from 'lucide-react';
|
|
5
|
-
import { cn } from '../../lib/utils';
|
|
5
|
+
import { cn } from '../../lib/utils.js';
|
|
6
6
|
const VIEWPORT = {
|
|
7
7
|
center: 'fixed inset-0 z-50 flex items-center justify-center p-4',
|
|
8
8
|
top: 'fixed inset-x-0 top-0 z-50 flex justify-center',
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
/** What happened to one line. */
|
|
3
|
+
export type DiffLineKind = 'context' | 'added' | 'removed';
|
|
4
|
+
/** One line of a change. */
|
|
5
|
+
export type DiffLine = {
|
|
6
|
+
/** What happened to it. @defaultValue 'context' */
|
|
7
|
+
kind?: DiffLineKind;
|
|
8
|
+
/**
|
|
9
|
+
* The number this line had before the change.
|
|
10
|
+
*
|
|
11
|
+
* A removed line has one and no new number, an added line the reverse, and a
|
|
12
|
+
* context line both. That asymmetry is the structural signal that says which
|
|
13
|
+
* side a line is on, and it is why the line numbers are the first thing in the
|
|
14
|
+
* markup rather than decoration beside the content.
|
|
15
|
+
*/
|
|
16
|
+
oldNumber?: number;
|
|
17
|
+
/** The number this line has after the change. */
|
|
18
|
+
newNumber?: number;
|
|
19
|
+
/** The line's text, exactly as it is in the file. */
|
|
20
|
+
content: string;
|
|
21
|
+
/**
|
|
22
|
+
* The character ranges within `content` that actually changed.
|
|
23
|
+
*
|
|
24
|
+
* Optional, and a line with none is drawn whole. This is what separates a diff
|
|
25
|
+
* that shows a line changed from one that shows what changed inside it, and it
|
|
26
|
+
* is the difference between reading a change and scanning for it.
|
|
27
|
+
*/
|
|
28
|
+
changed?: readonly (readonly [number, number])[];
|
|
29
|
+
};
|
|
30
|
+
/** The words a reader is told for each kind, because the Component ships none. */
|
|
31
|
+
export type DiffLabels = {
|
|
32
|
+
/** Read for a line that was added. */
|
|
33
|
+
added: string;
|
|
34
|
+
/** Read for a line that was removed. */
|
|
35
|
+
removed: string;
|
|
36
|
+
/** Read for a line that did not change. */
|
|
37
|
+
context: string;
|
|
38
|
+
};
|
|
39
|
+
/** The props the Diff accepts. */
|
|
40
|
+
export interface DiffProps extends Omit<ComponentProps<'div'>, 'children'> {
|
|
41
|
+
/** The lines, in file order. */
|
|
42
|
+
lines: readonly DiffLine[];
|
|
43
|
+
/**
|
|
44
|
+
* The accessible name of the change, read before its lines.
|
|
45
|
+
*
|
|
46
|
+
* Required rather than defaulted, because a page with two diffs is a page where
|
|
47
|
+
* a reader cannot tell which change they are in, and the name is the caller's
|
|
48
|
+
* word.
|
|
49
|
+
*/
|
|
50
|
+
label: string;
|
|
51
|
+
/**
|
|
52
|
+
* The words for each kind of line.
|
|
53
|
+
*
|
|
54
|
+
* Required, and the reason is the same one that makes a Dialog's close label a
|
|
55
|
+
* prop: a diff that announced "added" and "removed" in English would be a diff
|
|
56
|
+
* every consumer inherits in a language they did not choose. A shared library
|
|
57
|
+
* cannot know whether the word for this is "added" or "ajoute" or "hinzugefugt".
|
|
58
|
+
*/
|
|
59
|
+
labels: DiffLabels;
|
|
60
|
+
/** The name of the thing that changed, shown above the lines. */
|
|
61
|
+
file?: string;
|
|
62
|
+
/**
|
|
63
|
+
* A summary of the change, shown beside the file name.
|
|
64
|
+
*
|
|
65
|
+
* The caller's words, because a diff that computed "3 additions, 1 deletion"
|
|
66
|
+
* would be shipping a sentence. What it counts is left to the caller for the
|
|
67
|
+
* same reason, and because a diff of a rename has no additions at all.
|
|
68
|
+
*/
|
|
69
|
+
summary?: ReactNode;
|
|
70
|
+
/** Layout only. */
|
|
71
|
+
className?: string;
|
|
72
|
+
/** What a reader is told when there is nothing to show. */
|
|
73
|
+
empty?: ReactNode;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A change, as lines with the numbers they had and the numbers they have.
|
|
77
|
+
*
|
|
78
|
+
* **The bar is change density, not a side marker.** A diff conventionally marks
|
|
79
|
+
* each line with a coloured wash and a rail, which tells a reader that a line
|
|
80
|
+
* changed and nothing about how much. Rewriting one identifier in a long line
|
|
81
|
+
* leaves the same mark as replacing the whole line, so the reader's eye, which is
|
|
82
|
+
* fast at finding saturated bands, is drawn to the least interesting change in the
|
|
83
|
+
* file. Here the bar's width is the fraction of the line that actually changed, so
|
|
84
|
+
* the eye goes to the line that was rewritten rather than the line that was
|
|
85
|
+
* touched, and the marks that used to be a wash become a measurement.
|
|
86
|
+
*
|
|
87
|
+
* **The line numbers carry the side, not the colour.** An added line has a new
|
|
88
|
+
* number and no old one; a removed line the reverse. That asymmetry is structural,
|
|
89
|
+
* it is how every diff reader a developer has ever used distinguishes the two, and
|
|
90
|
+
* it does not depend on distinguishing red from green. The colour is redundant on
|
|
91
|
+
* top of it, which is the right way round: the shape carries the meaning and the
|
|
92
|
+
* colour reinforces it.
|
|
93
|
+
*
|
|
94
|
+
* **It is a table, because a diff is two columns of numbers beside a column of
|
|
95
|
+
* text.** Row and column navigation, the count of lines, and the association
|
|
96
|
+
* between a line and its number all come from the semantics rather than from a
|
|
97
|
+
* grid of divs, and a reader moving by row hears the file the way they read it.
|
|
98
|
+
*
|
|
99
|
+
* **The changed words are emphasised by weight.** See the note on the helper: a
|
|
100
|
+
* diff that tinted them would spend the two hues a reader is most likely to be
|
|
101
|
+
* unable to tell apart, and weight survives greyscale.
|
|
102
|
+
*/
|
|
103
|
+
declare function Diff({ lines, label, labels, file, summary, className, empty, ...props }: DiffProps): import("react").JSX.Element;
|
|
104
|
+
export { Diff };
|
|
105
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/components/ui/diff.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItD,iCAAiC;AACjC,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;AAE1D,4BAA4B;AAC5B,MAAM,MAAM,QAAQ,GAAG;IACrB,mDAAmD;IACnD,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAA;CACjD,CAAA;AAED,kFAAkF;AAClF,MAAM,MAAM,UAAU,GAAG;IACvB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,kCAAkC;AAClC,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACxE,gCAAgC;IAChC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IAC1B;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;OAOG;IACH,MAAM,EAAE,UAAU,CAAA;IAClB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,mBAAmB;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAgED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,iBAAS,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,+BA6H3F;AAED,OAAO,EAAE,IAAI,EAAE,CAAA"}
|