@exsto/ds 0.0.1-rc.1 → 0.0.1-rc.10

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 (148) hide show
  1. package/README.md +108 -27
  2. package/dist/chunks/date-range-picker-CWVcHgy2.js +204 -0
  3. package/dist/chunks/date-range-picker-CWVcHgy2.js.map +1 -0
  4. package/dist/chunks/input-syWxjY2U.js +172 -0
  5. package/dist/chunks/input-syWxjY2U.js.map +1 -0
  6. package/dist/chunks/toggle-CVnIkJVC.js +484 -0
  7. package/dist/chunks/toggle-CVnIkJVC.js.map +1 -0
  8. package/dist/date-picker.js +345 -0
  9. package/dist/date-picker.js.map +1 -0
  10. package/dist/ds/src/date-picker.d.ts +9 -0
  11. package/dist/ds/src/index.d.ts +2 -3
  12. package/dist/ds/src/rich-text-editor.d.ts +8 -0
  13. package/dist/index.js +4512 -2
  14. package/dist/index.js.map +1 -0
  15. package/dist/rich-text-editor.js +905 -0
  16. package/dist/rich-text-editor.js.map +1 -0
  17. package/dist/styles.css +915 -234
  18. package/dist/theme.css +308 -0
  19. package/dist/theme.css.d.ts +2 -0
  20. package/dist/ui/src/components/edyn/animated-number/animated-number.d.ts +30 -0
  21. package/dist/ui/src/components/edyn/animated-number/animated-number.test.d.ts +9 -0
  22. package/dist/ui/src/components/edyn/animated-number/index.d.ts +1 -0
  23. package/dist/ui/src/components/edyn/audio-player/audio-player.d.ts +3 -2
  24. package/dist/ui/src/components/edyn/date-picker/date-picker.d.ts +76 -0
  25. package/dist/ui/src/components/edyn/date-picker/date-picker.state.test.d.ts +9 -0
  26. package/dist/ui/src/components/edyn/date-picker/date-text.d.ts +40 -0
  27. package/dist/ui/src/components/edyn/date-picker/index.d.ts +2 -0
  28. package/dist/ui/src/components/edyn/date-range-picker/date-range-picker.d.ts +28 -0
  29. package/dist/ui/src/components/edyn/date-range-picker/date-range-picker.test.d.ts +9 -0
  30. package/dist/ui/src/components/edyn/date-range-picker/index.d.ts +1 -0
  31. package/dist/ui/src/components/edyn/initials-avatar/index.d.ts +1 -0
  32. package/dist/ui/src/components/edyn/initials-avatar/initials-avatar.d.ts +54 -0
  33. package/dist/ui/src/components/edyn/initials-avatar/initials-avatar.test.d.ts +10 -0
  34. package/dist/ui/src/components/edyn/multi-select/index.d.ts +1 -0
  35. package/dist/ui/src/components/edyn/multi-select/multi-select.d.ts +106 -0
  36. package/dist/ui/src/components/edyn/multi-select/multi-select.test.d.ts +9 -0
  37. package/dist/ui/src/components/edyn/progress-line/index.d.ts +1 -0
  38. package/dist/ui/src/components/edyn/progress-line/progress-line.d.ts +23 -0
  39. package/dist/ui/src/components/edyn/progress-line/progress-line.test.d.ts +9 -0
  40. package/dist/ui/src/components/edyn/rich-text-content/allow-list.d.ts +11 -0
  41. package/dist/ui/src/components/edyn/rich-text-content/index.d.ts +2 -0
  42. package/dist/ui/src/components/edyn/rich-text-content/rich-text-content.d.ts +22 -0
  43. package/dist/ui/src/components/edyn/rich-text-content/rich-text-content.test.d.ts +8 -0
  44. package/dist/ui/src/components/edyn/rich-text-editor/extensions.d.ts +18 -0
  45. package/dist/ui/src/components/edyn/rich-text-editor/index.d.ts +3 -0
  46. package/dist/ui/src/components/edyn/rich-text-editor/mention-list.d.ts +17 -0
  47. package/dist/ui/src/components/edyn/rich-text-editor/rich-text-editor.d.ts +53 -0
  48. package/dist/ui/src/components/edyn/rich-text-editor/rich-text-editor.test.d.ts +6 -0
  49. package/dist/ui/src/components/edyn/rich-text-editor/serialize.d.ts +13 -0
  50. package/dist/ui/src/components/edyn/rich-text-editor/sync.d.ts +19 -0
  51. package/dist/ui/src/components/edyn/rich-text-editor/sync.test.d.ts +11 -0
  52. package/dist/ui/src/components/edyn/rich-text-editor/toolbar.d.ts +20 -0
  53. package/dist/ui/src/components/edyn/rich-text-editor/types.d.ts +68 -0
  54. package/dist/ui/src/components/edyn/video-player/video-player.d.ts +2 -2
  55. package/dist/ui/src/components/forwarded-props.test.d.ts +8 -0
  56. package/dist/ui/src/components/ui/accordion/accordion.d.ts +9 -8
  57. package/dist/ui/src/components/ui/attachment/attachment.d.ts +1 -1
  58. package/dist/ui/src/components/ui/badge/badge.d.ts +1 -1
  59. package/dist/ui/src/components/ui/button/button.behavior.test.d.ts +8 -0
  60. package/dist/ui/src/components/ui/button/button.d.ts +1 -1
  61. package/dist/ui/src/components/ui/command/command.d.ts +17 -1
  62. package/dist/ui/src/components/ui/dropdown-menu/dropdown-menu.d.ts +12 -1
  63. package/dist/ui/src/components/ui/input-group/input-group.d.ts +1 -1
  64. package/dist/ui/src/components/ui/item/item.d.ts +1 -1
  65. package/dist/ui/src/components/ui/pagination/pagination.d.ts +3 -2
  66. package/dist/ui/src/components/ui/popover/popover.d.ts +1 -1
  67. package/dist/ui/src/components/ui/progress/progress.behavior.test.d.ts +8 -0
  68. package/dist/ui/src/components/ui/progress/progress.d.ts +43 -1
  69. package/dist/ui/src/components/ui/scroll-area/scroll-area.behavior.test.d.ts +12 -0
  70. package/dist/ui/src/components/ui/scroll-area/scroll-area.d.ts +59 -6
  71. package/dist/ui/src/components/ui/separator/separator.behavior.test.d.ts +14 -0
  72. package/dist/ui/src/components/ui/separator/separator.d.ts +14 -0
  73. package/dist/ui/src/components/ui/table/table.behavior.test.d.ts +4 -5
  74. package/dist/ui/src/components/ui/tabs/tabs.d.ts +9 -8
  75. package/dist/ui/src/index.d.ts +6 -0
  76. package/dist/ui/src/lib/first-weekday.d.ts +6 -0
  77. package/dist/ui/src/lib/focus-ring.test.d.ts +8 -0
  78. package/dist/ui/src/lib/popup-list.d.ts +47 -0
  79. package/dist/ui/src/lib/popup-list.test.d.ts +10 -0
  80. package/package.json +31 -8
  81. package/dist/chunks/toggle-group-ByNq8g7H.js +0 -4263
  82. package/dist/chunks/toggle-group-ByNq8g7H.js.map +0 -1
  83. package/dist/dom/src/context.d.ts +0 -34
  84. package/dist/dom/src/define-element.d.ts +0 -11
  85. package/dist/dom/src/field-control.d.ts +0 -5
  86. package/dist/dom/src/index.d.ts +0 -6
  87. package/dist/dom/src/mode.d.ts +0 -8
  88. package/dist/dom/src/styles.d.ts +0 -6
  89. package/dist/dom/src/theme-state.d.ts +0 -1
  90. package/dist/dom/src/types.d.ts +0 -65
  91. package/dist/ds/src/elements.d.ts +0 -12
  92. package/dist/elements/src/edx-accordion.d.ts +0 -14
  93. package/dist/elements/src/edx-accordion.test.d.ts +0 -1
  94. package/dist/elements/src/edx-alert.d.ts +0 -14
  95. package/dist/elements/src/edx-audio-player.d.ts +0 -11
  96. package/dist/elements/src/edx-avatar.d.ts +0 -10
  97. package/dist/elements/src/edx-badge.d.ts +0 -12
  98. package/dist/elements/src/edx-breadcrumb.d.ts +0 -11
  99. package/dist/elements/src/edx-button-group.d.ts +0 -7
  100. package/dist/elements/src/edx-button.d.ts +0 -20
  101. package/dist/elements/src/edx-calendar.d.ts +0 -21
  102. package/dist/elements/src/edx-card.d.ts +0 -8
  103. package/dist/elements/src/edx-checkbox.d.ts +0 -18
  104. package/dist/elements/src/edx-combobox.d.ts +0 -28
  105. package/dist/elements/src/edx-content-components.d.ts +0 -2
  106. package/dist/elements/src/edx-dialog.d.ts +0 -20
  107. package/dist/elements/src/edx-drawer.d.ts +0 -21
  108. package/dist/elements/src/edx-dropdown-menu.d.ts +0 -29
  109. package/dist/elements/src/edx-field.d.ts +0 -9
  110. package/dist/elements/src/edx-field.test.d.ts +0 -1
  111. package/dist/elements/src/edx-indicator.d.ts +0 -14
  112. package/dist/elements/src/edx-input-group.d.ts +0 -32
  113. package/dist/elements/src/edx-input-otp.d.ts +0 -19
  114. package/dist/elements/src/edx-input.d.ts +0 -31
  115. package/dist/elements/src/edx-interactive-components.d.ts +0 -2
  116. package/dist/elements/src/edx-label.d.ts +0 -6
  117. package/dist/elements/src/edx-pagination.d.ts +0 -8
  118. package/dist/elements/src/edx-popover.d.ts +0 -24
  119. package/dist/elements/src/edx-progress.d.ts +0 -10
  120. package/dist/elements/src/edx-radio-group.d.ts +0 -22
  121. package/dist/elements/src/edx-radio-group.test.d.ts +0 -1
  122. package/dist/elements/src/edx-scroll-area.d.ts +0 -15
  123. package/dist/elements/src/edx-scroll-area.test.d.ts +0 -1
  124. package/dist/elements/src/edx-select.d.ts +0 -34
  125. package/dist/elements/src/edx-separator.d.ts +0 -10
  126. package/dist/elements/src/edx-skeleton.d.ts +0 -8
  127. package/dist/elements/src/edx-slider.d.ts +0 -17
  128. package/dist/elements/src/edx-slider.test.d.ts +0 -1
  129. package/dist/elements/src/edx-switch.d.ts +0 -18
  130. package/dist/elements/src/edx-table.d.ts +0 -13
  131. package/dist/elements/src/edx-table.test.d.ts +0 -1
  132. package/dist/elements/src/edx-tabs.d.ts +0 -15
  133. package/dist/elements/src/edx-tabs.test.d.ts +0 -1
  134. package/dist/elements/src/edx-textarea.d.ts +0 -25
  135. package/dist/elements/src/edx-toggle-group.d.ts +0 -27
  136. package/dist/elements/src/edx-toggle-group.test.d.ts +0 -1
  137. package/dist/elements/src/edx-toggle.d.ts +0 -18
  138. package/dist/elements/src/edx-tooltip.d.ts +0 -28
  139. package/dist/elements/src/edx-video-player.d.ts +0 -16
  140. package/dist/elements/src/field-control-bridge.d.ts +0 -7
  141. package/dist/elements/src/index.d.ts +0 -14
  142. package/dist/elements/src/projected-content.test.d.ts +0 -1
  143. package/dist/elements/src/registry.d.ts +0 -39
  144. package/dist/elements/src/registry.test.d.ts +0 -1
  145. package/dist/elements.js +0 -4020
  146. package/dist/elements.js.map +0 -1
  147. /package/dist/{dom/src/define-element.test.d.ts → ui/src/components/edyn/date-picker/date-text.test.d.ts} +0 -0
  148. /package/dist/{dom/src/native-slot.test.d.ts → ui/src/lib/first-weekday.test.d.ts} +0 -0
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # @exsto/ds
2
2
 
3
- The eDynamix design system: React components, design tokens, and optional web
4
- components.
3
+ The eDynamix design system: React components and design tokens.
5
4
 
6
5
  ## Install
7
6
 
@@ -30,10 +29,40 @@ That is the whole setup. **You do not need Tailwind.** `styles.css` ships
30
29
  precompiled: it carries the design tokens plus every utility the components
31
30
  themselves use.
32
31
 
33
- If you *do* use Tailwind, note that `styles.css` does not generate utilities for
34
- your own markup. Your Tailwind build does that, as it already would; this file
35
- only guarantees the components look right. The tokens are plain CSS custom
36
- properties on `:root`, so your own styles can read them.
32
+ ### If you use Tailwind
33
+
34
+ `styles.css` is compiled output, so it only contains the utilities the components
35
+ themselves use. To write `bg-card` or `text-muted-foreground` in your *own*
36
+ markup, import the token layer as well and let your Tailwind build generate the
37
+ whole vocabulary:
38
+
39
+ ```css
40
+ @import "@exsto/ds/styles.css";
41
+ @import "tailwindcss";
42
+ @import "@exsto/ds/theme.css";
43
+ ```
44
+
45
+ **The order matters, and `styles.css` has to come first.** It is a compiled
46
+ Tailwind build, so its utilities land in the same cascade layer as yours, and at
47
+ equal specificity the later rule wins. Import it after your Tailwind entry and
48
+ its unconditional `.hidden` beats your `.md:table-cell`: responsive columns
49
+ vanish, widths collapse. Library CSS before app CSS, as with any CSS dependency.
50
+
51
+ Nothing else is needed. `theme.css` also points your build at the components'
52
+ shipped code, so your build emits their classes too, each responsive variant
53
+ after its own base. That is what keeps a design system class such as the
54
+ sidebar's `hidden md:block` working when your own markup uses `hidden` as well:
55
+ one build decides the order for both sides. Earlier releases needed a
56
+ `@source` line in the app to get this, and that line can be removed.
57
+
58
+ `theme.css` is uncompiled on purpose. It carries the tokens, the `.dark` scope,
59
+ the brand layer (Inter, `text-2xs`) and the `@theme` mapping Tailwind needs to
60
+ turn them into utilities. Do not copy that block into your app, or it will drift
61
+ from the design system.
62
+
63
+ Without it some token utilities still work, because our components happen to use
64
+ them, but the coverage is incidental: roughly half of `bg-*` and nearly every
65
+ `border-*` is absent.
37
66
 
38
67
  ### Dark mode
39
68
 
@@ -46,39 +75,91 @@ query, so a subtree can be dark inside a light page.
46
75
  </div>
47
76
  ```
48
77
 
49
- ## Web components
78
+ ## Entry points
50
79
 
51
- React is the default. If you are not on React, the same components ship as
52
- `<edx-*>` custom elements behind a subpath, so a React consumer never pays for a
53
- runtime it does not use.
80
+ | Import | What it is |
81
+ |---|---|
82
+ | `@exsto/ds` | React components |
83
+ | `@exsto/ds/date-picker` | The DatePicker (one day, typed or picked), on its own entry so the main one stays inside its size budget |
84
+ | `@exsto/ds/rich-text-editor` | The rich-text editor, on its own entry so its engine loads only where it is used |
85
+ | `@exsto/ds/styles.css` | Precompiled tokens and component styles |
86
+ | `@exsto/ds/theme.css` | Uncompiled tokens, brand layer, and the Tailwind `@theme` mapping |
87
+
88
+ ## Rich text
54
89
 
55
- ```ts
56
- import { registerElements } from '@exsto/ds/elements';
90
+ `RichTextEditor` is a small rich-text field: paragraphs, bold, italic, underline, bulleted and numbered lists, links and a horizontal line, with optional `@mentions` that your app searches. It lives on its own entry because it carries an editor engine (about 138 KB gzipped); an app that never imports it never pays for it.
57
91
 
58
- registerElements();
92
+ ```tsx
93
+ import { RichTextContent } from '@exsto/ds';
94
+ import { RichTextEditor } from '@exsto/ds/rich-text-editor';
95
+
96
+ <RichTextEditor
97
+ aria-label="Comment"
98
+ value={html}
99
+ onChange={setHtml} // "" when there is no text
100
+ minRows={3}
101
+ mention={{ search: async (query, { page, signal }) => fetchPeople(query, page, signal) }}
102
+ />;
103
+
104
+ <RichTextContent html={savedHtml} />;
59
105
  ```
60
106
 
61
- ```html
62
- <edx-button>Save</edx-button>
107
+ The value is HTML. **The editor emits only these elements and attributes**, whatever is typed or pasted (anything else is dropped on paste and on load, keeping its text), so a server allow-list can be exactly this; the same lists are exported as `RICH_TEXT_ELEMENTS`, `RICH_TEXT_ATTRIBUTES` and `RICH_TEXT_LINK_PROTOCOLS`:
108
+
109
+ | Element | Attributes |
110
+ |---|---|
111
+ | `p`, `br`, `hr`, `strong`, `em`, `u`, `ul`, `ol`, `li` | none (no `class`, no `style`) |
112
+ | `a` | `href`, which must be absolute `http`, `https` or `mailto` |
113
+
114
+ Strong and em, not b and i; no `target` or `rel` on links (add them when you render, as `RichTextContent` does). The editor is a convenience for the writer, not a security boundary: sanitise on the server as well.
115
+
116
+ **Mentions.** Typing `@` opens a list under the caret that calls `mention.search(query, { page, signal })` after a pause (250 ms by default), aborting the previous call. Return an array (one page) or `{ items, hasMore }` (the next page is asked for when the list is scrolled to its end). An item is `{ id, label, secondary? }`: the chip shows `label` while editing, and the HTML carries **plain text, `@${id}` followed by a space, and no element** (`mention.toText` changes that). A value loaded back into the editor shows that text as text, not as a chip. `RichTextContent` marks runs that look like `@person@example.test` and `@assignees` as pills.
117
+
118
+ Also: `ref` gives `insertText(text)` and `focus()` for buttons outside the editor; `fields` adds an "Insert a field" menu that writes `{{id}}`; `maxLength` refuses edits past a number of characters; `onPasteFiles` receives files pasted without any text; `invalid` and `aria-invalid`, `disabled`, `readOnly`, `placeholder`, `labels` (every string) and `toolbar={false}` do what they say. The box is `minRows` lines tall when empty and grows to `maxRows`, then scrolls inside.
119
+
120
+ ## Dates
121
+
122
+ `DatePicker` is one calendar day in a field: typed in the locale's order (`DD/MM/YYYY` for en-GB, `MM/DD/YYYY` for en-US) or picked from a calendar, read when the field is left, with a message under it when the text is not a day. It is on its own entry. The value is a `yyyy-mm-dd` string, not a `Date`, so no time zone moves it a day.
123
+
124
+ ```tsx
125
+ import { DatePicker } from '@exsto/ds/date-picker';
126
+
127
+ <DatePicker aria-label="Go-live date" value={day} onValueChange={setDay} min="2026-01-01" locale="en-GB" />;
63
128
  ```
64
129
 
65
- `registerElements()` defaults to shadow DOM and carries its own copy of the
66
- compiled stylesheet, because a shadow root does not inherit the page's styles.
67
- Pass `{ mode: 'light' }` to render into the light DOM instead, or `{ styles }` to
68
- supply your own sheet. Calling it more than once is harmless.
130
+ `onValueChange(day, state)` gets `undefined` as the day when the field is emptied or its text is not a usable day. The second argument says which: `{ kind: 'day' }`, `{ kind: 'empty' }`, or `{ kind: 'refused'; text; problem }`, where `text` is what was typed and `problem` the message the picker shows under the field. A caller that ignores the second argument keeps working. A required field uses it to show its own message only when the field is empty, so the person never reads two:
69
131
 
70
- ## Entry points
132
+ ```tsx
133
+ import { Field, FieldError, FieldLabel } from '@exsto/ds';
134
+ import { DatePicker, type TDatePickerState } from '@exsto/ds/date-picker';
135
+
136
+ const [day, setDay] = useState<string>();
137
+ const [state, setState] = useState<TDatePickerState>({ kind: 'empty' });
138
+ const missing = state.kind === 'empty'; // 'refused' is already said by the picker itself
139
+
140
+ <Field invalid={missing}>
141
+ <FieldLabel>Go-live date</FieldLabel>
142
+ <DatePicker
143
+ value={day}
144
+ onValueChange={(next, nextState) => {
145
+ setDay(next);
146
+ setState(nextState);
147
+ }}
148
+ />
149
+ <FieldError match={missing}>Enter the date.</FieldError>
150
+ </Field>;
151
+ ```
71
152
 
72
- | Import | What it is |
73
- |---|---|
74
- | `@exsto/ds` | React components (the default) |
75
- | `@exsto/ds/styles.css` | Precompiled tokens and component styles |
76
- | `@exsto/ds/elements` | `<edx-*>` custom elements and `registerElements()` |
153
+ Refused text is reported each time it changes, also when the field held no day before, and emptying the field afterwards reports `empty`. A parent's `aria-invalid` only draws the invalid border; the picker's own message is added to `aria-describedby` once, after the parent's. `DateRangePicker`, for a range, is in the main entry.
77
154
 
78
155
  ## Status
79
156
 
80
- `0.0.1-rc.1`. The API is not stable yet; treat minor versions as breaking until
81
- `0.1.0`.
157
+ Release candidates (`0.0.1-rc.N`). The API is not stable yet; treat minor versions
158
+ as breaking until `0.1.0`.
159
+
160
+ `0.0.1-rc.5` removed the `@exsto/ds/elements` entry point (the `<edx-*>` web
161
+ components) and with it Angular support. The design system is React only. Stay on
162
+ `0.0.1-rc.4` if you depend on the elements.
82
163
 
83
164
  ## Licence
84
165
 
@@ -0,0 +1,204 @@
1
+ import { c as Button, l as buttonVariants, n as Popover, r as PopoverContent, s as PopoverTrigger, u as cn } from "./input-syWxjY2U.js";
2
+ import * as React from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { IconCalendar, IconChevronDown, IconChevronLeft, IconChevronRight } from "@tabler/icons-react";
5
+ import { DayPicker, getDefaultClassNames } from "react-day-picker";
6
+ //#region ../ui/src/components/ui/calendar/calendar.tsx
7
+ var Calendar = ({ className, classNames, showOutsideDays = true, captionLayout = "label", buttonVariant = "ghost", locale, formatters, components, ...props }) => {
8
+ const defaultClassNames = getDefaultClassNames();
9
+ return /* @__PURE__ */ jsx(DayPicker, {
10
+ showOutsideDays,
11
+ className: cn("group/calendar bg-background p-2 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(7)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent", String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`, String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`, className),
12
+ captionLayout,
13
+ locale,
14
+ formatters: {
15
+ formatMonthDropdown: (date) => date.toLocaleString(locale?.code, { month: "short" }),
16
+ ...formatters
17
+ },
18
+ classNames: {
19
+ root: cn("w-fit", defaultClassNames.root),
20
+ months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
21
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
22
+ nav: cn("absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1", defaultClassNames.nav),
23
+ button_previous: cn(buttonVariants({ variant: buttonVariant }), "size-(--cell-size) p-0 select-none aria-disabled:opacity-50", defaultClassNames.button_previous),
24
+ button_next: cn(buttonVariants({ variant: buttonVariant }), "size-(--cell-size) p-0 select-none aria-disabled:opacity-50", defaultClassNames.button_next),
25
+ month_caption: cn("flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)", defaultClassNames.month_caption),
26
+ dropdowns: cn("flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium", defaultClassNames.dropdowns),
27
+ dropdown_root: cn("relative rounded-(--cell-radius)", defaultClassNames.dropdown_root),
28
+ dropdown: cn("absolute inset-0 bg-popover opacity-0", defaultClassNames.dropdown),
29
+ caption_label: cn("font-medium select-none", captionLayout === "label" ? "text-sm" : "flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground", defaultClassNames.caption_label),
30
+ month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
31
+ weekdays: cn("flex", defaultClassNames.weekdays),
32
+ weekday: cn("flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none", defaultClassNames.weekday),
33
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
34
+ week_number_header: cn("w-(--cell-size) select-none", defaultClassNames.week_number_header),
35
+ week_number: cn("text-[0.8rem] text-muted-foreground select-none", defaultClassNames.week_number),
36
+ day: cn("group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)", props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)" : "[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)", defaultClassNames.day),
37
+ range_start: cn("relative isolate z-0 rounded-l-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted", defaultClassNames.range_start),
38
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
39
+ range_end: cn("relative isolate z-0 rounded-r-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted", defaultClassNames.range_end),
40
+ today: cn("rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none", defaultClassNames.today),
41
+ outside: cn("text-muted-foreground aria-selected:text-muted-foreground", defaultClassNames.outside),
42
+ disabled: cn("text-muted-foreground opacity-50", defaultClassNames.disabled),
43
+ hidden: cn("invisible", defaultClassNames.hidden),
44
+ ...classNames
45
+ },
46
+ components: {
47
+ Root: ({ className, rootRef, ...props }) => {
48
+ return /* @__PURE__ */ jsx("div", {
49
+ "data-slot": "calendar",
50
+ ref: rootRef,
51
+ className: cn(className),
52
+ ...props
53
+ });
54
+ },
55
+ Chevron: ({ className, orientation, ...props }) => {
56
+ if (orientation === "left") return /* @__PURE__ */ jsx(IconChevronLeft, {
57
+ className: cn("size-4", className),
58
+ ...props
59
+ });
60
+ if (orientation === "right") return /* @__PURE__ */ jsx(IconChevronRight, {
61
+ className: cn("size-4", className),
62
+ ...props
63
+ });
64
+ return /* @__PURE__ */ jsx(IconChevronDown, {
65
+ className: cn("size-4", className),
66
+ ...props
67
+ });
68
+ },
69
+ DayButton: ({ ...props }) => /* @__PURE__ */ jsx(CalendarDayButton, {
70
+ locale,
71
+ ...props
72
+ }),
73
+ WeekNumber: ({ children, ...props }) => {
74
+ return /* @__PURE__ */ jsx("td", {
75
+ ...props,
76
+ children: /* @__PURE__ */ jsx("div", {
77
+ className: "flex size-(--cell-size) items-center justify-center text-center",
78
+ children
79
+ })
80
+ });
81
+ },
82
+ ...components
83
+ },
84
+ ...props
85
+ });
86
+ };
87
+ var CalendarDayButton = ({ className, day, modifiers, locale, ...props }) => {
88
+ const defaultClassNames = getDefaultClassNames();
89
+ const refButton = React.useRef(null);
90
+ React.useEffect(() => {
91
+ if (modifiers.focused) refButton.current?.focus();
92
+ }, [modifiers.focused]);
93
+ return /* @__PURE__ */ jsx(Button, {
94
+ ref: refButton,
95
+ variant: "ghost",
96
+ size: "icon",
97
+ "data-day": day.date.toLocaleDateString(locale?.code),
98
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
99
+ "data-range-start": modifiers.range_start,
100
+ "data-range-end": modifiers.range_end,
101
+ "data-range-middle": modifiers.range_middle,
102
+ className: cn("relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-foreground [&>span]:text-xs [&>span]:opacity-70", defaultClassNames.day, className),
103
+ ...props
104
+ });
105
+ };
106
+ //#endregion
107
+ //#region ../ui/src/hooks/use-mobile.ts
108
+ var MOBILE_BREAKPOINT = 768;
109
+ var useIsMobile = () => {
110
+ const [isMobile, setIsMobile] = React.useState(void 0);
111
+ React.useEffect(() => {
112
+ const mql = window.matchMedia(`(max-width: 767px)`);
113
+ const onChange = () => {
114
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
115
+ };
116
+ mql.addEventListener("change", onChange);
117
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
118
+ return () => mql.removeEventListener("change", onChange);
119
+ }, []);
120
+ return !!isMobile;
121
+ };
122
+ //#endregion
123
+ //#region ../ui/src/lib/first-weekday.ts
124
+ var SUNDAY_FIRST = /* @__PURE__ */ new Set([
125
+ "US",
126
+ "CA",
127
+ "MX",
128
+ "BR",
129
+ "JP",
130
+ "IL",
131
+ "IN",
132
+ "PH",
133
+ "ZA",
134
+ "KR",
135
+ "TW",
136
+ "HK",
137
+ "SA"
138
+ ]);
139
+ /**
140
+ * The weekday a locale starts its week on, 0 for Sunday to 6 for Saturday, from Intl, so en-GB starts on Monday and en-US on
141
+ * Sunday with no locale data of our own shipped. A browser without week info gets the region's usual start.
142
+ */
143
+ var firstWeekdayOf = (locale) => {
144
+ try {
145
+ const info = new Intl.Locale(locale);
146
+ const first = info.getWeekInfo?.().firstDay ?? info.weekInfo?.firstDay;
147
+ if (first !== void 0) return first % 7;
148
+ return SUNDAY_FIRST.has(info.region ?? "") ? 0 : 1;
149
+ } catch {
150
+ return 0;
151
+ }
152
+ };
153
+ //#endregion
154
+ //#region ../ui/src/components/edyn/date-range-picker/date-range-picker.tsx
155
+ var dayToDate = (value) => value === void 0 ? void 0 : /* @__PURE__ */ new Date(`${value}T12:00:00`);
156
+ var dateToDay = (date) => date === void 0 ? void 0 : `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
157
+ /** A range of calendar days, either end optional; two months side by side, one on a phone. */
158
+ var DateRangePicker = ({ id, value, onValueChange, placeholder = "Select date range", locale = "en-GB", summary = "range", "aria-label": ariaLabel, className, ...props }) => {
159
+ const isMobile = useIsMobile();
160
+ const from = dayToDate(value.from);
161
+ const to = dayToDate(value.to);
162
+ const format = new Intl.DateTimeFormat(locale, {
163
+ day: "2-digit",
164
+ month: "short",
165
+ year: "numeric"
166
+ });
167
+ const ends = [from, to].filter((date) => date !== void 0).map((date) => format.format(date));
168
+ return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsxs(PopoverTrigger, {
169
+ render: /* @__PURE__ */ jsx(Button, {
170
+ ...props,
171
+ id,
172
+ "aria-label": ariaLabel,
173
+ "data-slot": "date-range-picker-trigger",
174
+ "data-set": ends.length > 0 ? "" : void 0,
175
+ variant: "outline",
176
+ className: cn("w-full min-w-0 justify-start font-normal", ends.length === 0 && "text-muted-foreground", className)
177
+ }),
178
+ children: [/* @__PURE__ */ jsx(IconCalendar, { "aria-hidden": "true" }), /* @__PURE__ */ jsx("span", {
179
+ className: "truncate",
180
+ children: ends.length === 0 || summary === "label" ? placeholder : ends.join(" – ")
181
+ })]
182
+ }), /* @__PURE__ */ jsx(PopoverContent, {
183
+ align: "start",
184
+ className: "w-auto p-0",
185
+ children: /* @__PURE__ */ jsx(Calendar, {
186
+ mode: "range",
187
+ defaultMonth: from,
188
+ numberOfMonths: isMobile ? 1 : 2,
189
+ weekStartsOn: firstWeekdayOf(locale),
190
+ selected: {
191
+ from,
192
+ to
193
+ },
194
+ onSelect: (range) => onValueChange({
195
+ from: dateToDay(range?.from),
196
+ to: dateToDay(range?.to)
197
+ })
198
+ })
199
+ })] });
200
+ };
201
+ //#endregion
202
+ export { useIsMobile as a, firstWeekdayOf as i, dateToDay as n, Calendar as o, dayToDate as r, CalendarDayButton as s, DateRangePicker as t };
203
+
204
+ //# sourceMappingURL=date-range-picker-CWVcHgy2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-range-picker-CWVcHgy2.js","names":[],"sources":["../../../ui/src/components/ui/calendar/calendar.tsx","../../../ui/src/hooks/use-mobile.ts","../../../ui/src/lib/first-weekday.ts","../../../ui/src/components/edyn/date-range-picker/date-range-picker.tsx"],"sourcesContent":["import { cn } from '@edyn/ui/lib/utils';\nimport { IconChevronDown, IconChevronLeft, IconChevronRight } from '@tabler/icons-react';\nimport * as React from 'react';\nimport { type DayButton, DayPicker, getDefaultClassNames, type Locale } from 'react-day-picker';\nimport { Button, buttonVariants } from '../button';\n\nexport const Calendar = ({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = 'label',\n buttonVariant = 'ghost',\n locale,\n formatters,\n components,\n ...props\n}: React.ComponentProps<typeof DayPicker> & {\n buttonVariant?: React.ComponentProps<typeof Button>['variant'];\n}) => {\n const defaultClassNames = getDefaultClassNames();\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\n 'group/calendar bg-background p-2 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(7)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent',\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className,\n )}\n captionLayout={captionLayout}\n locale={locale}\n formatters={{\n formatMonthDropdown: (date) => date.toLocaleString(locale?.code, { month: 'short' }),\n ...formatters,\n }}\n classNames={{\n root: cn('w-fit', defaultClassNames.root),\n months: cn('relative flex flex-col gap-4 md:flex-row', defaultClassNames.months),\n month: cn('flex w-full flex-col gap-4', defaultClassNames.month),\n nav: cn('absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1', defaultClassNames.nav),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n 'size-(--cell-size) p-0 select-none aria-disabled:opacity-50',\n defaultClassNames.button_previous,\n ),\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n 'size-(--cell-size) p-0 select-none aria-disabled:opacity-50',\n defaultClassNames.button_next,\n ),\n month_caption: cn('flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)', defaultClassNames.month_caption),\n dropdowns: cn('flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium', defaultClassNames.dropdowns),\n dropdown_root: cn('relative rounded-(--cell-radius)', defaultClassNames.dropdown_root),\n dropdown: cn('absolute inset-0 bg-popover opacity-0', defaultClassNames.dropdown),\n caption_label: cn(\n 'font-medium select-none',\n captionLayout === 'label'\n ? 'text-sm'\n : 'flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground',\n defaultClassNames.caption_label,\n ),\n month_grid: cn('w-full border-collapse', defaultClassNames.month_grid),\n weekdays: cn('flex', defaultClassNames.weekdays),\n weekday: cn('flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none', defaultClassNames.weekday),\n week: cn('mt-2 flex w-full', defaultClassNames.week),\n week_number_header: cn('w-(--cell-size) select-none', defaultClassNames.week_number_header),\n week_number: cn('text-[0.8rem] text-muted-foreground select-none', defaultClassNames.week_number),\n day: cn(\n 'group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)',\n props.showWeekNumber\n ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)'\n : '[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)',\n defaultClassNames.day,\n ),\n range_start: cn(\n 'relative isolate z-0 rounded-l-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted',\n defaultClassNames.range_start,\n ),\n range_middle: cn('rounded-none', defaultClassNames.range_middle),\n range_end: cn(\n 'relative isolate z-0 rounded-r-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted',\n defaultClassNames.range_end,\n ),\n today: cn('rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none', defaultClassNames.today),\n outside: cn('text-muted-foreground aria-selected:text-muted-foreground', defaultClassNames.outside),\n disabled: cn('text-muted-foreground opacity-50', defaultClassNames.disabled),\n hidden: cn('invisible', defaultClassNames.hidden),\n ...classNames,\n }}\n components={{\n Root: ({ className, rootRef, ...props }) => {\n return <div data-slot=\"calendar\" ref={rootRef} className={cn(className)} {...props} />;\n },\n Chevron: ({ className, orientation, ...props }) => {\n if (orientation === 'left') {\n return <IconChevronLeft className={cn('size-4', className)} {...props} />;\n }\n\n if (orientation === 'right') {\n return <IconChevronRight className={cn('size-4', className)} {...props} />;\n }\n\n return <IconChevronDown className={cn('size-4', className)} {...props} />;\n },\n DayButton: ({ ...props }) => <CalendarDayButton locale={locale} {...props} />,\n WeekNumber: ({ children, ...props }) => {\n return (\n <td {...props}>\n <div className=\"flex size-(--cell-size) items-center justify-center text-center\">{children}</div>\n </td>\n );\n },\n ...components,\n }}\n {...props}\n />\n );\n};\n\nexport const CalendarDayButton = ({\n className,\n day,\n modifiers,\n locale,\n ...props\n}: React.ComponentProps<typeof DayButton> & { locale?: Partial<Locale> }) => {\n const defaultClassNames = getDefaultClassNames();\n\n const refButton = React.useRef<HTMLButtonElement>(null);\n React.useEffect(() => {\n if (modifiers.focused) {\n refButton.current?.focus();\n }\n }, [modifiers.focused]);\n\n return (\n <Button\n ref={refButton}\n variant=\"ghost\"\n size=\"icon\"\n data-day={day.date.toLocaleDateString(locale?.code)}\n data-selected-single={modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle}\n data-range-start={modifiers.range_start}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n className={cn(\n 'relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-foreground [&>span]:text-xs [&>span]:opacity-70',\n defaultClassNames.day,\n className,\n )}\n {...props}\n />\n );\n};\n","import * as React from 'react';\n\nconst MOBILE_BREAKPOINT = 768;\n\nexport const useIsMobile = () => {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n };\n mql.addEventListener('change', onChange);\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n return () => mql.removeEventListener('change', onChange);\n }, []);\n\n return !!isMobile;\n};\n","export type TWeekday = 0 | 1 | 2 | 3 | 4 | 5 | 6;\n\n// Regions whose week starts on a Sunday, for a browser that cannot say (Intl week info is not everywhere yet).\nconst SUNDAY_FIRST = new Set(['US', 'CA', 'MX', 'BR', 'JP', 'IL', 'IN', 'PH', 'ZA', 'KR', 'TW', 'HK', 'SA']);\n\n/**\n * The weekday a locale starts its week on, 0 for Sunday to 6 for Saturday, from Intl, so en-GB starts on Monday and en-US on\n * Sunday with no locale data of our own shipped. A browser without week info gets the region's usual start.\n */\nexport const firstWeekdayOf = (locale: string): TWeekday => {\n try {\n const info = new Intl.Locale(locale) as Intl.Locale & { getWeekInfo?: () => { firstDay: number }; weekInfo?: { firstDay: number } };\n const first = info.getWeekInfo?.().firstDay ?? info.weekInfo?.firstDay;\n if (first !== undefined) {\n // Intl counts Monday as 1 to Sunday as 7; the calendar counts Sunday as 0.\n return (first % 7) as TWeekday;\n }\n return SUNDAY_FIRST.has(info.region ?? '') ? 0 : 1;\n } catch {\n return 0;\n }\n};\n","import { Button } from '@edyn/ui/components/ui/button';\nimport { Calendar } from '@edyn/ui/components/ui/calendar';\nimport { Popover, PopoverContent, PopoverTrigger } from '@edyn/ui/components/ui/popover';\nimport { useIsMobile } from '@edyn/ui/hooks/use-mobile';\nimport { firstWeekdayOf } from '@edyn/ui/lib/first-weekday';\nimport { cn } from '@edyn/ui/lib/utils';\nimport { IconCalendar } from '@tabler/icons-react';\nimport type { ComponentPropsWithoutRef } from 'react';\n\n/** A range of calendar days as yyyy-mm-dd, either end optional. */\nexport type TDateRange = { from?: string; to?: string };\n\n// A calendar day is read and written at midday local time, so no time zone or daylight\n// saving change can move it onto the day before or after.\nexport const dayToDate = (value: string | undefined): Date | undefined => (value === undefined ? undefined : new Date(`${value}T12:00:00`));\n\nexport const dateToDay = (date: Date | undefined): string | undefined =>\n date === undefined ? undefined : `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;\n\n/** Anything else a button takes (data-*, aria-*, title) goes to the trigger. */\nexport interface IDateRangePickerProps\n extends Omit<ComponentPropsWithoutRef<'button'>, 'value' | 'defaultValue' | 'placeholder' | 'id' | 'className' | 'children' | 'onChange' | 'type'> {\n id?: string;\n value: TDateRange;\n onValueChange: (value: TDateRange) => void;\n placeholder?: string;\n /**\n * What the trigger says once a range is set. `range` (default) writes the ends; `label` keeps the label, so a\n * range the page shows elsewhere (as a removable chip, say) is not repeated here. In both, the trigger carries\n * `data-set` while either end is set, for a look of its own.\n */\n summary?: 'range' | 'label';\n /** How the ends are written on the trigger, and which weekday the calendar starts on (BCP 47); en-GB reads 05 Mar 2026 and starts on Monday. */\n locale?: string;\n /** An accessible name for the trigger, when there is no visible label to point at. */\n 'aria-label'?: string;\n className?: string;\n}\n\n/** A range of calendar days, either end optional; two months side by side, one on a phone. */\nexport const DateRangePicker = ({\n id,\n value,\n onValueChange,\n placeholder = 'Select date range',\n locale = 'en-GB',\n summary = 'range',\n 'aria-label': ariaLabel,\n className,\n ...props\n}: IDateRangePickerProps) => {\n const isMobile = useIsMobile();\n const from = dayToDate(value.from);\n const to = dayToDate(value.to);\n const format = new Intl.DateTimeFormat(locale, { day: '2-digit', month: 'short', year: 'numeric' });\n const ends = [from, to].filter((date) => date !== undefined).map((date) => format.format(date));\n return (\n <Popover>\n <PopoverTrigger\n render={\n <Button\n {...props}\n id={id}\n aria-label={ariaLabel}\n data-slot=\"date-range-picker-trigger\"\n data-set={ends.length > 0 ? '' : undefined}\n variant=\"outline\"\n className={cn('w-full min-w-0 justify-start font-normal', ends.length === 0 && 'text-muted-foreground', className)}\n />\n }\n >\n <IconCalendar aria-hidden=\"true\" />\n <span className=\"truncate\">{ends.length === 0 || summary === 'label' ? placeholder : ends.join(' – ')}</span>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-auto p-0\">\n <Calendar\n mode=\"range\"\n defaultMonth={from}\n numberOfMonths={isMobile ? 1 : 2}\n weekStartsOn={firstWeekdayOf(locale)}\n selected={{ from, to }}\n onSelect={(range) => onValueChange({ from: dateToDay(range?.from), to: dateToDay(range?.to) })}\n />\n </PopoverContent>\n </Popover>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ import { isValidElement } from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Button } from "@base-ui/react/button";
4
+ import { clsx } from "clsx";
5
+ import { twMerge } from "tailwind-merge";
6
+ import { cva } from "class-variance-authority";
7
+ import { Popover } from "@base-ui/react/popover";
8
+ import { Input } from "@base-ui/react/input";
9
+ //#region ../ui/src/lib/utils.ts
10
+ var cn = (...inputs) => twMerge(clsx(inputs));
11
+ /**
12
+ * Normalise a size prop to a CSS length.
13
+ *
14
+ * Bare numbers become px, which is also what a bare numeric *string* means: an
15
+ * element attribute arrives as a string, so `width="480"` and `width={480}` have
16
+ * to land on the same value. Anything with a unit, a percentage or a keyword
17
+ * passes through untouched.
18
+ */
19
+ var cssLength = (value) => {
20
+ if (value == null || value === "") return;
21
+ if (typeof value === "number") return Number.isFinite(value) ? `${value}px` : void 0;
22
+ return /^-?\d*\.?\d+$/.test(value.trim()) ? `${value.trim()}px` : value;
23
+ };
24
+ //#endregion
25
+ //#region ../ui/src/components/ui/button/button.tsx
26
+ /**
27
+ * The fill of a disabled Button that has one: muted, whichever way it is disabled (a button's own disabled, Base UI's
28
+ * data-disabled, or aria-disabled on a link), in the dark theme too, where the variants set their own fill. Ghost and link
29
+ * have no fill to begin with and are given none: a grey box would turn a link into a button.
30
+ */
31
+ var DISABLED_FILL = "disabled:bg-muted data-disabled:bg-muted aria-disabled:bg-muted dark:disabled:bg-muted dark:data-disabled:bg-muted dark:aria-disabled:bg-muted";
32
+ var buttonVariants = cva("group/button inline-flex shrink-0 cursor-pointer items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all motion-reduce:transition-none motion-reduce:transform-none outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:not-aria-disabled:translate-y-px disabled:pointer-events-none disabled:border-transparent disabled:text-foreground/60 disabled:shadow-none disabled:focus-visible:ring-0 dark:disabled:border-transparent data-link-disabled:pointer-events-none data-link-disabled:focus-visible:ring-0 data-disabled:border-transparent data-disabled:text-foreground/60 data-disabled:shadow-none dark:data-disabled:border-transparent aria-disabled:border-transparent aria-disabled:text-foreground/60 aria-disabled:shadow-none dark:aria-disabled:border-transparent aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
33
+ variants: {
34
+ variant: {
35
+ default: `bg-primary text-primary-foreground hover:bg-primary/80 ${DISABLED_FILL}`,
36
+ outline: `border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50 ${DISABLED_FILL}`,
37
+ secondary: `bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground ${DISABLED_FILL}`,
38
+ ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50 aria-disabled:hover:bg-transparent dark:aria-disabled:hover:bg-transparent",
39
+ destructive: `bg-destructive/10 text-destructive hover:bg-destructive/15 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/15 dark:hover:bg-destructive/20 dark:focus-visible:ring-destructive/40 ${DISABLED_FILL}`,
40
+ link: "text-primary underline-offset-4 hover:underline aria-disabled:hover:no-underline"
41
+ },
42
+ size: {
43
+ default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
44
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
45
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
46
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
47
+ icon: "size-8",
48
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
49
+ "icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
50
+ "icon-lg": "size-9"
51
+ }
52
+ },
53
+ defaultVariants: {
54
+ variant: "default",
55
+ size: "default"
56
+ }
57
+ });
58
+ /**
59
+ * Whether this Button is rendering a link rather than a button, so it can keep
60
+ * link semantics. Covers `render={<a href="..." />}` and a routing component
61
+ * that takes an `href` (Next's Link). A component with a different prop for its
62
+ * destination (react-router's `to`) cannot be recognised from here: give those
63
+ * `nativeButton={false} role={undefined}` directly.
64
+ */
65
+ var rendersALink = (render) => isValidElement(render) && (render.type === "a" || typeof render.props.href === "string");
66
+ /**
67
+ * A link that looks like a button is still a link, and has to be announced as
68
+ * one: it opens in a new tab, it has an address, Enter follows it and Space
69
+ * scrolls the page.
70
+ *
71
+ * Base UI needs telling, in two steps. Rendering an anchor while `nativeButton`
72
+ * is true (its default) warns in development and puts `type="button"` on the
73
+ * anchor; following the warning and passing `nativeButton={false}` then adds
74
+ * `role="button"`, which is what takes the link semantics away. So this does
75
+ * both: non-native, with the role and the tabindex Base UI would add cleared
76
+ * again. An explicit prop from the caller still wins over either.
77
+ */
78
+ var LINK_PROPS = {
79
+ nativeButton: false,
80
+ role: void 0,
81
+ tabIndex: void 0
82
+ };
83
+ /**
84
+ * A disabled link is not :disabled (only a form control can be), so the markup has to say it: Base UI already marks it
85
+ * `aria-disabled` and `data-disabled` and stops the click, and this takes it out of the tab order, which LINK_PROPS
86
+ * would otherwise leave to the browser. The href is kept on purpose, so a routing component that requires one keeps
87
+ * working; the pointer is kept off the link by `data-link-disabled:pointer-events-none`, which also covers a middle
88
+ * click and the context menu, and the click and Enter are stopped by Base UI. It is a data attribute of its own, not
89
+ * `aria-disabled`, because an aria-disabled button (`focusableWhenDisabled`) is meant to stay hoverable and focusable so it
90
+ * can say why it cannot act; only a native :disabled button and this link are inert.
91
+ */
92
+ var DISABLED_LINK_PROPS = {
93
+ ...LINK_PROPS,
94
+ tabIndex: -1,
95
+ "data-link-disabled": ""
96
+ };
97
+ var Button$1 = ({ className, variant = "default", size = "default", ...props }) => {
98
+ return /* @__PURE__ */ jsx(Button, {
99
+ "data-slot": "button",
100
+ ...rendersALink(props.render) ? props.disabled ? DISABLED_LINK_PROPS : LINK_PROPS : {},
101
+ className: cn(buttonVariants({
102
+ variant,
103
+ size,
104
+ className
105
+ })),
106
+ ...props
107
+ });
108
+ };
109
+ //#endregion
110
+ //#region ../ui/src/components/ui/popover/popover.tsx
111
+ var Popover$1 = ({ ...props }) => {
112
+ return /* @__PURE__ */ jsx(Popover.Root, {
113
+ "data-slot": "popover",
114
+ ...props
115
+ });
116
+ };
117
+ var PopoverTrigger = ({ ...props }) => {
118
+ return /* @__PURE__ */ jsx(Popover.Trigger, {
119
+ "data-slot": "popover-trigger",
120
+ ...props
121
+ });
122
+ };
123
+ var PopoverContent = ({ className, align = "center", alignOffset = 0, side = "bottom", sideOffset = 4, anchor, ...props }) => {
124
+ return /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
125
+ align,
126
+ alignOffset,
127
+ anchor,
128
+ side,
129
+ sideOffset,
130
+ className: "isolate z-50",
131
+ children: /* @__PURE__ */ jsx(Popover.Popup, {
132
+ "data-slot": "popover-content",
133
+ className: cn("z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 motion-reduce:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
134
+ ...props
135
+ })
136
+ }) });
137
+ };
138
+ var PopoverHeader = ({ className, ...props }) => {
139
+ return /* @__PURE__ */ jsx("div", {
140
+ "data-slot": "popover-header",
141
+ className: cn("flex flex-col gap-0.5 text-sm", className),
142
+ ...props
143
+ });
144
+ };
145
+ var PopoverTitle = ({ className, ...props }) => {
146
+ return /* @__PURE__ */ jsx(Popover.Title, {
147
+ "data-slot": "popover-title",
148
+ className: cn("font-medium", className),
149
+ ...props
150
+ });
151
+ };
152
+ var PopoverDescription = ({ className, ...props }) => {
153
+ return /* @__PURE__ */ jsx(Popover.Description, {
154
+ "data-slot": "popover-description",
155
+ className: cn("text-muted-foreground", className),
156
+ ...props
157
+ });
158
+ };
159
+ //#endregion
160
+ //#region ../ui/src/components/ui/input/input.tsx
161
+ var Input$1 = ({ className, type, ...props }) => {
162
+ return /* @__PURE__ */ jsx(Input, {
163
+ type,
164
+ "data-slot": "input",
165
+ className: cn("h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", className),
166
+ ...props
167
+ });
168
+ };
169
+ //#endregion
170
+ export { PopoverHeader as a, Button$1 as c, cssLength as d, PopoverDescription as i, buttonVariants as l, Popover$1 as n, PopoverTitle as o, PopoverContent as r, PopoverTrigger as s, Input$1 as t, cn as u };
171
+
172
+ //# sourceMappingURL=input-syWxjY2U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-syWxjY2U.js","names":[],"sources":["../../../ui/src/lib/utils.ts","../../../ui/src/components/ui/button/button.tsx","../../../ui/src/components/ui/popover/popover.tsx","../../../ui/src/components/ui/input/input.tsx"],"sourcesContent":["import type { ClassValue } from 'clsx';\nimport { clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport const cn = (...inputs: ClassValue[]): string => twMerge(clsx(inputs));\n\n/** A CSS length as a component prop: a number is px, a string is used verbatim. */\nexport type TCssLength = number | string;\n\n/**\n * Normalise a size prop to a CSS length.\n *\n * Bare numbers become px, which is also what a bare numeric *string* means: an\n * element attribute arrives as a string, so `width=\"480\"` and `width={480}` have\n * to land on the same value. Anything with a unit, a percentage or a keyword\n * passes through untouched.\n */\nexport const cssLength = (value: TCssLength | null | undefined): string | undefined => {\n if (value == null || value === '') {\n return undefined;\n }\n\n if (typeof value === 'number') {\n return Number.isFinite(value) ? `${value}px` : undefined;\n }\n\n return /^-?\\d*\\.?\\d+$/.test(value.trim()) ? `${value.trim()}px` : value;\n};\n","import { Button as ButtonPrimitive } from '@base-ui/react/button';\nimport { cn } from '@edyn/ui/lib/utils';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { isValidElement } from 'react';\n\n/**\n * The fill of a disabled Button that has one: muted, whichever way it is disabled (a button's own disabled, Base UI's\n * data-disabled, or aria-disabled on a link), in the dark theme too, where the variants set their own fill. Ghost and link\n * have no fill to begin with and are given none: a grey box would turn a link into a button.\n */\nconst DISABLED_FILL =\n 'disabled:bg-muted data-disabled:bg-muted aria-disabled:bg-muted dark:disabled:bg-muted dark:data-disabled:bg-muted dark:aria-disabled:bg-muted';\n\nexport const buttonVariants = cva(\n \"group/button inline-flex shrink-0 cursor-pointer items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all motion-reduce:transition-none motion-reduce:transform-none outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:not-aria-disabled:translate-y-px disabled:pointer-events-none disabled:border-transparent disabled:text-foreground/60 disabled:shadow-none disabled:focus-visible:ring-0 dark:disabled:border-transparent data-link-disabled:pointer-events-none data-link-disabled:focus-visible:ring-0 data-disabled:border-transparent data-disabled:text-foreground/60 data-disabled:shadow-none dark:data-disabled:border-transparent aria-disabled:border-transparent aria-disabled:text-foreground/60 aria-disabled:shadow-none dark:aria-disabled:border-transparent aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: `bg-primary text-primary-foreground hover:bg-primary/80 ${DISABLED_FILL}`,\n outline: `border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50 ${DISABLED_FILL}`,\n secondary: `bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground ${DISABLED_FILL}`,\n ghost:\n 'hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50 aria-disabled:hover:bg-transparent dark:aria-disabled:hover:bg-transparent',\n destructive: `bg-destructive/10 text-destructive hover:bg-destructive/15 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/15 dark:hover:bg-destructive/20 dark:focus-visible:ring-destructive/40 ${DISABLED_FILL}`,\n link: 'text-primary underline-offset-4 hover:underline aria-disabled:hover:no-underline',\n },\n size: {\n default: 'h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: 'h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',\n icon: 'size-8',\n 'icon-xs': \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm': 'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',\n 'icon-lg': 'size-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\n/**\n * Whether this Button is rendering a link rather than a button, so it can keep\n * link semantics. Covers `render={<a href=\"...\" />}` and a routing component\n * that takes an `href` (Next's Link). A component with a different prop for its\n * destination (react-router's `to`) cannot be recognised from here: give those\n * `nativeButton={false} role={undefined}` directly.\n */\nconst rendersALink = (render: ButtonPrimitive.Props['render']): boolean =>\n isValidElement(render) && (render.type === 'a' || typeof (render.props as { href?: unknown }).href === 'string');\n\n/**\n * A link that looks like a button is still a link, and has to be announced as\n * one: it opens in a new tab, it has an address, Enter follows it and Space\n * scrolls the page.\n *\n * Base UI needs telling, in two steps. Rendering an anchor while `nativeButton`\n * is true (its default) warns in development and puts `type=\"button\"` on the\n * anchor; following the warning and passing `nativeButton={false}` then adds\n * `role=\"button\"`, which is what takes the link semantics away. So this does\n * both: non-native, with the role and the tabindex Base UI would add cleared\n * again. An explicit prop from the caller still wins over either.\n */\nconst LINK_PROPS = { nativeButton: false, role: undefined, tabIndex: undefined } as const;\n\n/**\n * A disabled link is not :disabled (only a form control can be), so the markup has to say it: Base UI already marks it\n * `aria-disabled` and `data-disabled` and stops the click, and this takes it out of the tab order, which LINK_PROPS\n * would otherwise leave to the browser. The href is kept on purpose, so a routing component that requires one keeps\n * working; the pointer is kept off the link by `data-link-disabled:pointer-events-none`, which also covers a middle\n * click and the context menu, and the click and Enter are stopped by Base UI. It is a data attribute of its own, not\n * `aria-disabled`, because an aria-disabled button (`focusableWhenDisabled`) is meant to stay hoverable and focusable so it\n * can say why it cannot act; only a native :disabled button and this link are inert.\n */\nconst DISABLED_LINK_PROPS = { ...LINK_PROPS, tabIndex: -1, 'data-link-disabled': '' } as const;\n\nexport const Button = ({\n className,\n variant = 'default',\n size = 'default',\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) => {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n {...(rendersALink(props.render) ? (props.disabled ? DISABLED_LINK_PROPS : LINK_PROPS) : {})}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n};\n","import { Popover as PopoverPrimitive } from '@base-ui/react/popover';\nimport { cn } from '@edyn/ui/lib/utils';\nimport type * as React from 'react';\n\nexport const Popover = ({ ...props }: PopoverPrimitive.Root.Props) => {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n};\n\nexport const PopoverTrigger = ({ ...props }: PopoverPrimitive.Trigger.Props) => {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n};\n\nexport const PopoverContent = ({\n className,\n align = 'center',\n alignOffset = 0,\n side = 'bottom',\n sideOffset = 4,\n anchor,\n ...props\n}: PopoverPrimitive.Popup.Props & Pick<PopoverPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'anchor' | 'side' | 'sideOffset'>) => {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n anchor={anchor}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <PopoverPrimitive.Popup\n data-slot=\"popover-content\"\n className={cn(\n 'z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 motion-reduce:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n );\n};\n\nexport const PopoverHeader = ({ className, ...props }: React.ComponentProps<'div'>) => {\n return <div data-slot=\"popover-header\" className={cn('flex flex-col gap-0.5 text-sm', className)} {...props} />;\n};\n\nexport const PopoverTitle = ({ className, ...props }: PopoverPrimitive.Title.Props) => {\n return <PopoverPrimitive.Title data-slot=\"popover-title\" className={cn('font-medium', className)} {...props} />;\n};\n\nexport const PopoverDescription = ({ className, ...props }: PopoverPrimitive.Description.Props) => {\n return <PopoverPrimitive.Description data-slot=\"popover-description\" className={cn('text-muted-foreground', className)} {...props} />;\n};\n","import { Input as InputPrimitive } from '@base-ui/react/input';\nimport { cn } from '@edyn/ui/lib/utils';\nimport type * as React from 'react';\n\nexport const Input = ({ className, type, ...props }: React.ComponentProps<'input'>) => {\n return (\n <InputPrimitive\n type={type}\n data-slot=\"input\"\n className={cn(\n 'h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40',\n className,\n )}\n {...props}\n />\n );\n};\n"],"mappings":"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"}