@open-mercato/core 0.6.7-develop.6785.1.1dd7cfac55 → 0.6.7-develop.6795.1.8a3f27921c

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 (196) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities.ids.generated.js +1 -0
  3. package/dist/generated/entities.ids.generated.js.map +2 -2
  4. package/dist/modules/auth/backend/settings/page.js +14 -9
  5. package/dist/modules/auth/backend/settings/page.js.map +2 -2
  6. package/dist/modules/customers/cli.js +17 -7
  7. package/dist/modules/customers/cli.js.map +2 -2
  8. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +229 -216
  9. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  10. package/dist/modules/customers/search.js +50 -29
  11. package/dist/modules/customers/search.js.map +2 -2
  12. package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
  13. package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
  14. package/dist/modules/data_sync/api/mappings/route.js +13 -4
  15. package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
  16. package/dist/modules/data_sync/api/options.js +7 -2
  17. package/dist/modules/data_sync/api/options.js.map +2 -2
  18. package/dist/modules/data_sync/api/run.js +7 -2
  19. package/dist/modules/data_sync/api/run.js.map +2 -2
  20. package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
  21. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
  22. package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
  23. package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
  24. package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
  25. package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
  26. package/dist/modules/data_sync/api/runs.js +7 -2
  27. package/dist/modules/data_sync/api/runs.js.map +2 -2
  28. package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
  29. package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
  30. package/dist/modules/data_sync/api/schedules/route.js +13 -4
  31. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  32. package/dist/modules/data_sync/api/validate.js +9 -4
  33. package/dist/modules/data_sync/api/validate.js.map +2 -2
  34. package/dist/modules/design_system/acl.js +9 -0
  35. package/dist/modules/design_system/acl.js.map +7 -0
  36. package/dist/modules/design_system/backend/design-system/page.js +11 -0
  37. package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
  38. package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
  39. package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
  40. package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
  41. package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
  42. package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
  43. package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
  44. package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
  45. package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
  46. package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
  47. package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
  48. package/dist/modules/design_system/gallery/entries/banners.js +186 -0
  49. package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
  50. package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
  51. package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
  52. package/dist/modules/design_system/gallery/entries/charts.js +457 -0
  53. package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
  54. package/dist/modules/design_system/gallery/entries/dates.js +306 -0
  55. package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
  56. package/dist/modules/design_system/gallery/entries/detail.js +358 -0
  57. package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
  58. package/dist/modules/design_system/gallery/entries/display.js +785 -0
  59. package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
  60. package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
  61. package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
  62. package/dist/modules/design_system/gallery/entries/filters.js +505 -0
  63. package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
  64. package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
  65. package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
  66. package/dist/modules/design_system/gallery/entries/icons.js +140 -0
  67. package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
  68. package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
  69. package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
  70. package/dist/modules/design_system/gallery/entries/messages.js +334 -0
  71. package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
  72. package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
  73. package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
  74. package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
  75. package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
  76. package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
  77. package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
  78. package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
  79. package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
  80. package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
  81. package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
  82. package/dist/modules/design_system/gallery/registry.js +139 -0
  83. package/dist/modules/design_system/gallery/registry.js.map +7 -0
  84. package/dist/modules/design_system/gallery/types.js +1 -0
  85. package/dist/modules/design_system/gallery/types.js.map +7 -0
  86. package/dist/modules/design_system/index.js +9 -0
  87. package/dist/modules/design_system/index.js.map +7 -0
  88. package/dist/modules/design_system/setup.js +14 -0
  89. package/dist/modules/design_system/setup.js.map +7 -0
  90. package/dist/modules/inbox_ops/search.js +15 -4
  91. package/dist/modules/inbox_ops/search.js.map +2 -2
  92. package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
  93. package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
  94. package/dist/modules/integrations/api/[id]/health/route.js +6 -3
  95. package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
  96. package/dist/modules/integrations/api/[id]/route.js +6 -3
  97. package/dist/modules/integrations/api/[id]/route.js.map +2 -2
  98. package/dist/modules/integrations/api/[id]/state/route.js +6 -3
  99. package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
  100. package/dist/modules/integrations/api/[id]/version/route.js +6 -3
  101. package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
  102. package/dist/modules/integrations/api/logs/route.js +6 -3
  103. package/dist/modules/integrations/api/logs/route.js.map +2 -2
  104. package/dist/modules/integrations/api/route.js +6 -3
  105. package/dist/modules/integrations/api/route.js.map +2 -2
  106. package/dist/modules/integrations/api/umes-read.js +2 -2
  107. package/dist/modules/integrations/api/umes-read.js.map +2 -2
  108. package/dist/modules/integrations/lib/organization-scope.js +2 -9
  109. package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
  110. package/dist/modules/messages/search.js +10 -5
  111. package/dist/modules/messages/search.js.map +2 -2
  112. package/dist/modules/query_index/data/entities.js +2 -1
  113. package/dist/modules/query_index/data/entities.js.map +2 -2
  114. package/dist/modules/query_index/lib/engine.js +32 -50
  115. package/dist/modules/query_index/lib/engine.js.map +2 -2
  116. package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
  117. package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
  118. package/generated/entities.ids.generated.ts +1 -0
  119. package/package.json +16 -16
  120. package/src/modules/auth/backend/settings/page.tsx +17 -8
  121. package/src/modules/customers/cli.ts +17 -7
  122. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +24 -13
  123. package/src/modules/customers/i18n/de.json +17 -0
  124. package/src/modules/customers/i18n/en.json +17 -0
  125. package/src/modules/customers/i18n/es.json +17 -0
  126. package/src/modules/customers/i18n/pl.json +17 -0
  127. package/src/modules/customers/search.ts +59 -27
  128. package/src/modules/data_sync/AGENTS.md +1 -0
  129. package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
  130. package/src/modules/data_sync/api/mappings/route.ts +13 -4
  131. package/src/modules/data_sync/api/options.ts +7 -2
  132. package/src/modules/data_sync/api/run.ts +7 -2
  133. package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
  134. package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
  135. package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
  136. package/src/modules/data_sync/api/runs.ts +7 -2
  137. package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
  138. package/src/modules/data_sync/api/schedules/route.ts +13 -4
  139. package/src/modules/data_sync/api/validate.ts +9 -4
  140. package/src/modules/design_system/AGENTS.md +34 -0
  141. package/src/modules/design_system/acl.ts +5 -0
  142. package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
  143. package/src/modules/design_system/backend/design-system/page.tsx +14 -0
  144. package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
  145. package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
  146. package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
  147. package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
  148. package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
  149. package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
  150. package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
  151. package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
  152. package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
  153. package/src/modules/design_system/gallery/entries/display.tsx +893 -0
  154. package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
  155. package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
  156. package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
  157. package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
  158. package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
  159. package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
  160. package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
  161. package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
  162. package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
  163. package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
  164. package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
  165. package/src/modules/design_system/gallery/registry.ts +152 -0
  166. package/src/modules/design_system/gallery/types.ts +32 -0
  167. package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
  168. package/src/modules/design_system/i18n/de.json +46 -0
  169. package/src/modules/design_system/i18n/en.json +46 -0
  170. package/src/modules/design_system/i18n/es.json +46 -0
  171. package/src/modules/design_system/i18n/pl.json +46 -0
  172. package/src/modules/design_system/index.ts +7 -0
  173. package/src/modules/design_system/setup.ts +12 -0
  174. package/src/modules/inbox_ops/i18n/de.json +3 -0
  175. package/src/modules/inbox_ops/i18n/en.json +3 -0
  176. package/src/modules/inbox_ops/i18n/es.json +3 -0
  177. package/src/modules/inbox_ops/i18n/pl.json +3 -0
  178. package/src/modules/inbox_ops/search.ts +20 -4
  179. package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
  180. package/src/modules/integrations/api/[id]/health/route.ts +6 -3
  181. package/src/modules/integrations/api/[id]/route.ts +6 -3
  182. package/src/modules/integrations/api/[id]/state/route.ts +6 -3
  183. package/src/modules/integrations/api/[id]/version/route.ts +6 -3
  184. package/src/modules/integrations/api/logs/route.ts +6 -3
  185. package/src/modules/integrations/api/route.ts +6 -3
  186. package/src/modules/integrations/api/umes-read.ts +2 -2
  187. package/src/modules/integrations/lib/organization-scope.ts +5 -25
  188. package/src/modules/messages/i18n/de.json +2 -0
  189. package/src/modules/messages/i18n/en.json +2 -0
  190. package/src/modules/messages/i18n/es.json +2 -0
  191. package/src/modules/messages/i18n/pl.json +2 -0
  192. package/src/modules/messages/search.ts +11 -5
  193. package/src/modules/query_index/data/entities.ts +7 -0
  194. package/src/modules/query_index/lib/engine.ts +40 -63
  195. package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
  196. package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
@@ -0,0 +1,1516 @@
1
+ import * as React from 'react'
2
+ import { Copy, Globe, Info, Link2, Send, User } from 'lucide-react'
3
+ import { Input } from '@open-mercato/ui/primitives/input'
4
+ import { Textarea } from '@open-mercato/ui/primitives/textarea'
5
+ import {
6
+ Select,
7
+ SelectContent,
8
+ SelectGroup,
9
+ SelectItem,
10
+ SelectLabel,
11
+ SelectSeparator,
12
+ SelectTrigger,
13
+ SelectTriggerLeading,
14
+ SelectValue,
15
+ } from '@open-mercato/ui/primitives/select'
16
+ import { CompactSelectTrigger } from '@open-mercato/ui/primitives/compact-select'
17
+ import { InlineSelectTrigger } from '@open-mercato/ui/primitives/inline-select'
18
+ import { InlineInput } from '@open-mercato/ui/primitives/inline-input'
19
+ import { Checkbox } from '@open-mercato/ui/primitives/checkbox'
20
+ import { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'
21
+ import { Radio, RadioGroup } from '@open-mercato/ui/primitives/radio'
22
+ import { RadioField } from '@open-mercato/ui/primitives/radio-field'
23
+ import { Switch } from '@open-mercato/ui/primitives/switch'
24
+ import { SwitchField } from '@open-mercato/ui/primitives/switch-field'
25
+ import { Slider } from '@open-mercato/ui/primitives/slider'
26
+ import { FormField } from '@open-mercato/ui/primitives/form-field'
27
+ import { SearchInput } from '@open-mercato/ui/primitives/search-input'
28
+ import { EmailInput } from '@open-mercato/ui/primitives/email-input'
29
+ import { PasswordInput } from '@open-mercato/ui/primitives/password-input'
30
+ import { WebsiteInput } from '@open-mercato/ui/primitives/website-input'
31
+ import { AmountInput, type AmountValue } from '@open-mercato/ui/primitives/amount-input'
32
+ import { CounterInput } from '@open-mercato/ui/primitives/counter-input'
33
+ import { DigitInput } from '@open-mercato/ui/primitives/digit-input'
34
+ import { CardInput } from '@open-mercato/ui/primitives/card-input'
35
+ import { ButtonInput } from '@open-mercato/ui/primitives/button-input'
36
+ import {
37
+ ColorPicker,
38
+ COLOR_PICKER_DEFAULT_SWATCHES,
39
+ } from '@open-mercato/ui/primitives/color-picker'
40
+ import { TagInput } from '@open-mercato/ui/primitives/tag-input'
41
+ import { RichEditor } from '@open-mercato/ui/primitives/rich-editor'
42
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
43
+ import type { GalleryEntry } from '../types'
44
+
45
+ // Component titles and variant names are proper nouns from the codebase and
46
+ // are deliberately not translated. `code` MUST contain the entry's importPath
47
+ // (enforced by the registry-integrity test) and is always reviewed alongside
48
+ // its sibling `render`.
49
+
50
+ // ---------------------------------------------------------------------------
51
+ // Demo wrappers — controlled primitives need local state to be interactive in
52
+ // the gallery. The `code` snippets show the essential consumer usage, not
53
+ // these wrappers.
54
+ // ---------------------------------------------------------------------------
55
+
56
+ function DemoSearchInput({ size }: { size?: 'sm' | 'default' | 'lg' }) {
57
+ const [value, setValue] = React.useState('open orders')
58
+ return (
59
+ <div className="w-72">
60
+ <SearchInput value={value} onChange={setValue} size={size} />
61
+ </div>
62
+ )
63
+ }
64
+
65
+ function DemoAmountInput({ showCurrency }: { showCurrency?: boolean }) {
66
+ const [value, setValue] = React.useState<AmountValue>({ amount: '1250.00', currency: 'EUR' })
67
+ return (
68
+ <div className="w-72">
69
+ <AmountInput value={value} onChange={setValue} showCurrency={showCurrency} />
70
+ </div>
71
+ )
72
+ }
73
+
74
+ function DemoCounterInput({
75
+ initial = 2,
76
+ step,
77
+ precision,
78
+ min,
79
+ max,
80
+ }: {
81
+ initial?: number
82
+ step?: number
83
+ precision?: number
84
+ min?: number
85
+ max?: number
86
+ }) {
87
+ const [value, setValue] = React.useState<number | null>(initial)
88
+ return (
89
+ <div className="w-36">
90
+ <CounterInput
91
+ value={value}
92
+ onChange={setValue}
93
+ step={step}
94
+ precision={precision}
95
+ min={min}
96
+ max={max}
97
+ />
98
+ </div>
99
+ )
100
+ }
101
+
102
+ function DemoCardInput({ initial = '' }: { initial?: string }) {
103
+ const [value, setValue] = React.useState(initial)
104
+ return (
105
+ <div className="w-80">
106
+ <CardInput value={value} onChange={setValue} />
107
+ </div>
108
+ )
109
+ }
110
+
111
+ function DemoColorPicker({
112
+ allowCustom,
113
+ swatches,
114
+ }: {
115
+ allowCustom?: boolean
116
+ swatches?: readonly string[]
117
+ }) {
118
+ const [color, setColor] = React.useState('#6366F1')
119
+ return (
120
+ <ColorPicker
121
+ value={color}
122
+ onChange={setColor}
123
+ allowCustom={allowCustom}
124
+ swatches={swatches}
125
+ aria-label="Pick color"
126
+ />
127
+ )
128
+ }
129
+
130
+ function DemoTagInput({
131
+ initial = [],
132
+ maxTags,
133
+ placeholder,
134
+ }: {
135
+ initial?: string[]
136
+ maxTags?: number
137
+ placeholder?: string
138
+ }) {
139
+ const [tags, setTags] = React.useState<string[]>(initial)
140
+ return (
141
+ <div className="w-72">
142
+ <TagInput value={tags} onChange={setTags} maxTags={maxTags} placeholder={placeholder} />
143
+ </div>
144
+ )
145
+ }
146
+
147
+ function DemoRichEditor({ variant }: { variant: 'minimal' | 'standard' }) {
148
+ const [html, setHtml] = React.useState(
149
+ '<p>Ship the <strong>Q3 release notes</strong> before Friday.</p>',
150
+ )
151
+ return (
152
+ <div className="w-full max-w-xl">
153
+ <RichEditor value={html} onChange={setHtml} variant={variant} />
154
+ </div>
155
+ )
156
+ }
157
+
158
+ // ---------------------------------------------------------------------------
159
+ // Entries
160
+ // ---------------------------------------------------------------------------
161
+
162
+ const inputEntry: GalleryEntry = {
163
+ id: 'input',
164
+ title: 'Input',
165
+ importPath: '@open-mercato/ui/primitives/input',
166
+ variants: [
167
+ {
168
+ id: 'default',
169
+ title: 'default',
170
+ render: () => (
171
+ <div className="w-72">
172
+ <Input placeholder="Product name" />
173
+ </div>
174
+ ),
175
+ code: `import { Input } from '@open-mercato/ui/primitives/input'
176
+
177
+ <Input placeholder="Product name" />`,
178
+ },
179
+ {
180
+ id: 'icon-slots',
181
+ title: 'Icon slots',
182
+ render: () => (
183
+ <>
184
+ <div className="w-56">
185
+ <Input leftIcon={<User />} placeholder="Assignee" />
186
+ </div>
187
+ <div className="w-56">
188
+ <Input rightIcon={<Info />} placeholder="SKU" />
189
+ </div>
190
+ </>
191
+ ),
192
+ code: `import { Info, User } from 'lucide-react'
193
+ import { Input } from '@open-mercato/ui/primitives/input'
194
+
195
+ <Input leftIcon={<User />} placeholder="Assignee" />
196
+ <Input rightIcon={<Info />} placeholder="SKU" />`,
197
+ },
198
+ {
199
+ id: 'sizes',
200
+ title: 'Sizes',
201
+ render: () => (
202
+ <>
203
+ <div className="w-44">
204
+ <Input size="lg" placeholder="Large" />
205
+ </div>
206
+ <div className="w-44">
207
+ <Input size="default" placeholder="Default" />
208
+ </div>
209
+ <div className="w-44">
210
+ <Input size="sm" placeholder="Small" />
211
+ </div>
212
+ </>
213
+ ),
214
+ code: `import { Input } from '@open-mercato/ui/primitives/input'
215
+
216
+ <Input size="lg" placeholder="Large" />
217
+ <Input size="default" placeholder="Default" />
218
+ <Input size="sm" placeholder="Small" />`,
219
+ },
220
+ {
221
+ id: 'states',
222
+ title: 'States',
223
+ render: () => (
224
+ <>
225
+ <div className="w-56">
226
+ <Input aria-invalid defaultValue="not-a-number" />
227
+ </div>
228
+ <div className="w-56">
229
+ <Input disabled placeholder="Disabled" />
230
+ </div>
231
+ </>
232
+ ),
233
+ code: `import { Input } from '@open-mercato/ui/primitives/input'
234
+
235
+ <Input aria-invalid defaultValue="not-a-number" />
236
+ <Input disabled placeholder="Disabled" />`,
237
+ },
238
+ ],
239
+ }
240
+
241
+ const textareaEntry: GalleryEntry = {
242
+ id: 'textarea',
243
+ title: 'Textarea',
244
+ importPath: '@open-mercato/ui/primitives/textarea',
245
+ variants: [
246
+ {
247
+ id: 'default',
248
+ title: 'default',
249
+ render: () => (
250
+ <div className="w-80">
251
+ <Textarea placeholder="Internal note for the fulfillment team" />
252
+ </div>
253
+ ),
254
+ code: `import { Textarea } from '@open-mercato/ui/primitives/textarea'
255
+
256
+ <Textarea placeholder="Internal note for the fulfillment team" />`,
257
+ },
258
+ {
259
+ id: 'character-count',
260
+ title: 'Character counter',
261
+ render: () => (
262
+ <div className="w-80">
263
+ <Textarea
264
+ showCount
265
+ maxLength={200}
266
+ defaultValue="Customer prefers delivery after 4 PM."
267
+ />
268
+ </div>
269
+ ),
270
+ code: `import { Textarea } from '@open-mercato/ui/primitives/textarea'
271
+
272
+ <Textarea showCount maxLength={200} defaultValue="Customer prefers delivery after 4 PM." />`,
273
+ },
274
+ {
275
+ id: 'states',
276
+ title: 'States',
277
+ render: () => (
278
+ <>
279
+ <div className="w-72">
280
+ <Textarea aria-invalid defaultValue="Too short" />
281
+ </div>
282
+ <div className="w-72">
283
+ <Textarea disabled placeholder="Disabled" />
284
+ </div>
285
+ </>
286
+ ),
287
+ code: `import { Textarea } from '@open-mercato/ui/primitives/textarea'
288
+
289
+ <Textarea aria-invalid defaultValue="Too short" />
290
+ <Textarea disabled placeholder="Disabled" />`,
291
+ },
292
+ ],
293
+ }
294
+
295
+ const selectEntry: GalleryEntry = {
296
+ id: 'select',
297
+ title: 'Select',
298
+ importPath: '@open-mercato/ui/primitives/select',
299
+ variants: [
300
+ {
301
+ id: 'default',
302
+ title: 'default',
303
+ render: () => (
304
+ <div className="w-56">
305
+ <Select defaultValue="pln">
306
+ <SelectTrigger>
307
+ <SelectValue placeholder="Choose currency" />
308
+ </SelectTrigger>
309
+ <SelectContent>
310
+ <SelectItem value="eur">Euro (EUR)</SelectItem>
311
+ <SelectItem value="pln">Polish Złoty (PLN)</SelectItem>
312
+ <SelectItem value="usd">US Dollar (USD)</SelectItem>
313
+ </SelectContent>
314
+ </Select>
315
+ </div>
316
+ ),
317
+ code: `import {
318
+ Select,
319
+ SelectContent,
320
+ SelectItem,
321
+ SelectTrigger,
322
+ SelectValue,
323
+ } from '@open-mercato/ui/primitives/select'
324
+
325
+ <Select defaultValue="pln">
326
+ <SelectTrigger>
327
+ <SelectValue placeholder="Choose currency" />
328
+ </SelectTrigger>
329
+ <SelectContent>
330
+ <SelectItem value="eur">Euro (EUR)</SelectItem>
331
+ <SelectItem value="pln">Polish Złoty (PLN)</SelectItem>
332
+ <SelectItem value="usd">US Dollar (USD)</SelectItem>
333
+ </SelectContent>
334
+ </Select>`,
335
+ },
336
+ {
337
+ id: 'groups-leading',
338
+ title: 'Groups + leading slot',
339
+ render: () => (
340
+ <div className="w-56">
341
+ <Select>
342
+ <SelectTrigger>
343
+ <SelectTriggerLeading>
344
+ <Globe />
345
+ </SelectTriggerLeading>
346
+ <SelectValue placeholder="Sales channel" />
347
+ </SelectTrigger>
348
+ <SelectContent>
349
+ <SelectGroup>
350
+ <SelectLabel>Online</SelectLabel>
351
+ <SelectItem value="webstore">Webstore</SelectItem>
352
+ <SelectItem value="marketplace">Marketplace</SelectItem>
353
+ </SelectGroup>
354
+ <SelectSeparator />
355
+ <SelectGroup>
356
+ <SelectLabel>Offline</SelectLabel>
357
+ <SelectItem value="retail">Retail store</SelectItem>
358
+ </SelectGroup>
359
+ </SelectContent>
360
+ </Select>
361
+ </div>
362
+ ),
363
+ code: `import { Globe } from 'lucide-react'
364
+ import {
365
+ Select,
366
+ SelectContent,
367
+ SelectGroup,
368
+ SelectItem,
369
+ SelectLabel,
370
+ SelectSeparator,
371
+ SelectTrigger,
372
+ SelectTriggerLeading,
373
+ SelectValue,
374
+ } from '@open-mercato/ui/primitives/select'
375
+
376
+ <Select>
377
+ <SelectTrigger>
378
+ <SelectTriggerLeading><Globe /></SelectTriggerLeading>
379
+ <SelectValue placeholder="Sales channel" />
380
+ </SelectTrigger>
381
+ <SelectContent>
382
+ <SelectGroup>
383
+ <SelectLabel>Online</SelectLabel>
384
+ <SelectItem value="webstore">Webstore</SelectItem>
385
+ <SelectItem value="marketplace">Marketplace</SelectItem>
386
+ </SelectGroup>
387
+ <SelectSeparator />
388
+ <SelectGroup>
389
+ <SelectLabel>Offline</SelectLabel>
390
+ <SelectItem value="retail">Retail store</SelectItem>
391
+ </SelectGroup>
392
+ </SelectContent>
393
+ </Select>`,
394
+ },
395
+ {
396
+ id: 'sizes',
397
+ title: 'Sizes',
398
+ render: () => (
399
+ <>
400
+ {(['lg', 'default', 'sm', 'xs'] as const).map((size) => (
401
+ <div key={size} className="w-40">
402
+ <Select defaultValue="active">
403
+ <SelectTrigger size={size}>
404
+ <SelectValue />
405
+ </SelectTrigger>
406
+ <SelectContent>
407
+ <SelectItem value="active">Active</SelectItem>
408
+ <SelectItem value="archived">Archived</SelectItem>
409
+ </SelectContent>
410
+ </Select>
411
+ </div>
412
+ ))}
413
+ </>
414
+ ),
415
+ code: `import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@open-mercato/ui/primitives/select'
416
+
417
+ <SelectTrigger size="lg" />
418
+ <SelectTrigger size="default" />
419
+ <SelectTrigger size="sm" />
420
+ <SelectTrigger size="xs" />`,
421
+ },
422
+ {
423
+ id: 'states',
424
+ title: 'States',
425
+ render: () => (
426
+ <>
427
+ <div className="w-48">
428
+ <Select>
429
+ <SelectTrigger aria-invalid="true">
430
+ <SelectValue placeholder="Required" />
431
+ </SelectTrigger>
432
+ <SelectContent>
433
+ <SelectItem value="a">Option A</SelectItem>
434
+ </SelectContent>
435
+ </Select>
436
+ </div>
437
+ <div className="w-48">
438
+ <Select>
439
+ <SelectTrigger disabled>
440
+ <SelectValue placeholder="Disabled" />
441
+ </SelectTrigger>
442
+ <SelectContent>
443
+ <SelectItem value="a">Option A</SelectItem>
444
+ </SelectContent>
445
+ </Select>
446
+ </div>
447
+ </>
448
+ ),
449
+ code: `import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@open-mercato/ui/primitives/select'
450
+
451
+ <SelectTrigger aria-invalid="true"><SelectValue placeholder="Required" /></SelectTrigger>
452
+ <SelectTrigger disabled><SelectValue placeholder="Disabled" /></SelectTrigger>`,
453
+ },
454
+ ],
455
+ }
456
+
457
+ const compactSelectEntry: GalleryEntry = {
458
+ id: 'compact-select',
459
+ title: 'CompactSelectTrigger',
460
+ importPath: '@open-mercato/ui/primitives/compact-select',
461
+ variants: [
462
+ {
463
+ id: 'trigger-label',
464
+ title: 'With trigger label',
465
+ render: () => (
466
+ <div className="w-44">
467
+ <Select defaultValue="newest">
468
+ <CompactSelectTrigger triggerLabel="Sort:">
469
+ <SelectValue />
470
+ </CompactSelectTrigger>
471
+ <SelectContent>
472
+ <SelectItem value="newest">Newest</SelectItem>
473
+ <SelectItem value="oldest">Oldest</SelectItem>
474
+ <SelectItem value="value">Highest value</SelectItem>
475
+ </SelectContent>
476
+ </Select>
477
+ </div>
478
+ ),
479
+ code: `import {
480
+ CompactSelectTrigger,
481
+ Select,
482
+ SelectContent,
483
+ SelectItem,
484
+ SelectValue,
485
+ } from '@open-mercato/ui/primitives/compact-select'
486
+
487
+ <Select defaultValue="newest">
488
+ <CompactSelectTrigger triggerLabel="Sort:">
489
+ <SelectValue />
490
+ </CompactSelectTrigger>
491
+ <SelectContent>
492
+ <SelectItem value="newest">Newest</SelectItem>
493
+ <SelectItem value="oldest">Oldest</SelectItem>
494
+ <SelectItem value="value">Highest value</SelectItem>
495
+ </SelectContent>
496
+ </Select>`,
497
+ },
498
+ {
499
+ id: 'plain',
500
+ title: 'Without label',
501
+ render: () => (
502
+ <div className="w-36">
503
+ <Select defaultValue="table">
504
+ <CompactSelectTrigger>
505
+ <SelectValue />
506
+ </CompactSelectTrigger>
507
+ <SelectContent>
508
+ <SelectItem value="table">Table</SelectItem>
509
+ <SelectItem value="board">Board</SelectItem>
510
+ </SelectContent>
511
+ </Select>
512
+ </div>
513
+ ),
514
+ code: `import {
515
+ CompactSelectTrigger,
516
+ Select,
517
+ SelectContent,
518
+ SelectItem,
519
+ SelectValue,
520
+ } from '@open-mercato/ui/primitives/compact-select'
521
+
522
+ <Select defaultValue="table">
523
+ <CompactSelectTrigger>
524
+ <SelectValue />
525
+ </CompactSelectTrigger>
526
+ <SelectContent>
527
+ <SelectItem value="table">Table</SelectItem>
528
+ <SelectItem value="board">Board</SelectItem>
529
+ </SelectContent>
530
+ </Select>`,
531
+ },
532
+ ],
533
+ }
534
+
535
+ const inlineSelectEntry: GalleryEntry = {
536
+ id: 'inline-select',
537
+ title: 'InlineSelectTrigger',
538
+ importPath: '@open-mercato/ui/primitives/inline-select',
539
+ variants: [
540
+ {
541
+ id: 'default',
542
+ title: 'default (border on hover)',
543
+ render: () => (
544
+ <div className="w-40">
545
+ <Select defaultValue="high">
546
+ <InlineSelectTrigger>
547
+ <SelectValue />
548
+ </InlineSelectTrigger>
549
+ <SelectContent>
550
+ <SelectItem value="low">Low</SelectItem>
551
+ <SelectItem value="medium">Medium</SelectItem>
552
+ <SelectItem value="high">High</SelectItem>
553
+ </SelectContent>
554
+ </Select>
555
+ </div>
556
+ ),
557
+ code: `import {
558
+ InlineSelectTrigger,
559
+ Select,
560
+ SelectContent,
561
+ SelectItem,
562
+ SelectValue,
563
+ } from '@open-mercato/ui/primitives/inline-select'
564
+
565
+ <Select defaultValue="high">
566
+ <InlineSelectTrigger>
567
+ <SelectValue />
568
+ </InlineSelectTrigger>
569
+ <SelectContent>
570
+ <SelectItem value="low">Low</SelectItem>
571
+ <SelectItem value="medium">Medium</SelectItem>
572
+ <SelectItem value="high">High</SelectItem>
573
+ </SelectContent>
574
+ </Select>`,
575
+ },
576
+ {
577
+ id: 'invisible',
578
+ title: 'Invisible until focus',
579
+ render: () => (
580
+ <div className="w-40">
581
+ <Select defaultValue="draft">
582
+ <InlineSelectTrigger showBorderOnHover={false}>
583
+ <SelectValue />
584
+ </InlineSelectTrigger>
585
+ <SelectContent>
586
+ <SelectItem value="draft">Draft</SelectItem>
587
+ <SelectItem value="published">Published</SelectItem>
588
+ </SelectContent>
589
+ </Select>
590
+ </div>
591
+ ),
592
+ code: `import {
593
+ InlineSelectTrigger,
594
+ Select,
595
+ SelectContent,
596
+ SelectItem,
597
+ SelectValue,
598
+ } from '@open-mercato/ui/primitives/inline-select'
599
+
600
+ <InlineSelectTrigger showBorderOnHover={false}>
601
+ <SelectValue />
602
+ </InlineSelectTrigger>`,
603
+ },
604
+ ],
605
+ }
606
+
607
+ const inlineInputEntry: GalleryEntry = {
608
+ id: 'inline-input',
609
+ title: 'InlineInput',
610
+ importPath: '@open-mercato/ui/primitives/inline-input',
611
+ variants: [
612
+ {
613
+ id: 'default',
614
+ title: 'default (border on hover)',
615
+ render: () => (
616
+ <div className="w-56">
617
+ <InlineInput defaultValue="Aurora desk lamp" aria-label="Product name" />
618
+ </div>
619
+ ),
620
+ code: `import { InlineInput } from '@open-mercato/ui/primitives/inline-input'
621
+
622
+ <InlineInput defaultValue="Aurora desk lamp" aria-label="Product name" onBlur={save} />`,
623
+ },
624
+ {
625
+ id: 'invisible',
626
+ title: 'Invisible until focus',
627
+ render: () => (
628
+ <div className="w-56">
629
+ <InlineInput
630
+ showBorderOnHover={false}
631
+ defaultValue="SKU-2041"
632
+ aria-label="SKU"
633
+ />
634
+ </div>
635
+ ),
636
+ code: `import { InlineInput } from '@open-mercato/ui/primitives/inline-input'
637
+
638
+ <InlineInput showBorderOnHover={false} defaultValue="SKU-2041" aria-label="SKU" />`,
639
+ },
640
+ ],
641
+ }
642
+
643
+ const checkboxEntry: GalleryEntry = {
644
+ id: 'checkbox',
645
+ title: 'Checkbox',
646
+ importPath: '@open-mercato/ui/primitives/checkbox',
647
+ variants: [
648
+ {
649
+ id: 'states',
650
+ title: 'States',
651
+ render: () => (
652
+ <>
653
+ <Checkbox aria-label="Unchecked" />
654
+ <Checkbox defaultChecked aria-label="Checked" />
655
+ <Checkbox checked="indeterminate" aria-label="Indeterminate" />
656
+ </>
657
+ ),
658
+ code: `import { Checkbox } from '@open-mercato/ui/primitives/checkbox'
659
+
660
+ <Checkbox />
661
+ <Checkbox defaultChecked />
662
+ <Checkbox checked="indeterminate" />`,
663
+ },
664
+ {
665
+ id: 'sizes',
666
+ title: 'Sizes',
667
+ render: () => (
668
+ <>
669
+ <Checkbox size="sm" defaultChecked aria-label="Small" />
670
+ <Checkbox size="md" defaultChecked aria-label="Medium" />
671
+ </>
672
+ ),
673
+ code: `import { Checkbox } from '@open-mercato/ui/primitives/checkbox'
674
+
675
+ <Checkbox size="sm" defaultChecked />
676
+ <Checkbox size="md" defaultChecked />`,
677
+ },
678
+ {
679
+ id: 'disabled',
680
+ title: 'Disabled',
681
+ render: () => (
682
+ <>
683
+ <Checkbox disabled aria-label="Disabled" />
684
+ <Checkbox disabled defaultChecked aria-label="Disabled checked" />
685
+ </>
686
+ ),
687
+ code: `import { Checkbox } from '@open-mercato/ui/primitives/checkbox'
688
+
689
+ <Checkbox disabled />
690
+ <Checkbox disabled defaultChecked />`,
691
+ },
692
+ ],
693
+ }
694
+
695
+ const checkboxFieldEntry: GalleryEntry = {
696
+ id: 'checkbox-field',
697
+ title: 'CheckboxField',
698
+ importPath: '@open-mercato/ui/primitives/checkbox-field',
699
+ variants: [
700
+ {
701
+ id: 'default',
702
+ title: 'default',
703
+ render: () => (
704
+ <CheckboxField label="Email notifications" defaultChecked />
705
+ ),
706
+ code: `import { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'
707
+
708
+ <CheckboxField label="Email notifications" defaultChecked />`,
709
+ },
710
+ {
711
+ id: 'with-description',
712
+ title: 'With sublabel + description',
713
+ render: () => (
714
+ <div className="w-80">
715
+ <CheckboxField
716
+ label="Auto-archive"
717
+ sublabel="(recommended)"
718
+ description="Closed conversations move to the archive after 30 days."
719
+ />
720
+ </div>
721
+ ),
722
+ code: `import { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'
723
+
724
+ <CheckboxField
725
+ label="Auto-archive"
726
+ sublabel="(recommended)"
727
+ description="Closed conversations move to the archive after 30 days."
728
+ />`,
729
+ },
730
+ {
731
+ id: 'flip',
732
+ title: 'Flipped (checkbox right)',
733
+ render: () => (
734
+ <div className="w-72">
735
+ <CheckboxField flip label="Include shipping costs" defaultChecked />
736
+ </div>
737
+ ),
738
+ code: `import { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'
739
+
740
+ <CheckboxField flip label="Include shipping costs" defaultChecked />`,
741
+ },
742
+ ],
743
+ }
744
+
745
+ const radioEntry: GalleryEntry = {
746
+ id: 'radio',
747
+ title: 'Radio',
748
+ importPath: '@open-mercato/ui/primitives/radio',
749
+ keywords: ['radiobutton', 'radio button', 'option group'],
750
+ variants: [
751
+ {
752
+ id: 'group',
753
+ title: 'RadioGroup',
754
+ render: () => (
755
+ <RadioGroup defaultValue="card" className="flex-row gap-3" aria-label="Payment method">
756
+ <Radio value="card" aria-label="Card" />
757
+ <Radio value="transfer" aria-label="Bank transfer" />
758
+ <Radio value="cash" aria-label="Cash" />
759
+ </RadioGroup>
760
+ ),
761
+ code: `import { Radio, RadioGroup } from '@open-mercato/ui/primitives/radio'
762
+
763
+ <RadioGroup defaultValue="card" aria-label="Payment method">
764
+ <Radio value="card" aria-label="Card" />
765
+ <Radio value="transfer" aria-label="Bank transfer" />
766
+ <Radio value="cash" aria-label="Cash" />
767
+ </RadioGroup>`,
768
+ },
769
+ {
770
+ id: 'disabled',
771
+ title: 'Disabled',
772
+ render: () => (
773
+ <RadioGroup defaultValue="a" disabled className="flex-row gap-3" aria-label="Disabled group">
774
+ <Radio value="a" aria-label="Selected disabled" />
775
+ <Radio value="b" aria-label="Unselected disabled" />
776
+ </RadioGroup>
777
+ ),
778
+ code: `import { Radio, RadioGroup } from '@open-mercato/ui/primitives/radio'
779
+
780
+ <RadioGroup defaultValue="a" disabled>
781
+ <Radio value="a" />
782
+ <Radio value="b" />
783
+ </RadioGroup>`,
784
+ },
785
+ ],
786
+ }
787
+
788
+ const radioFieldEntry: GalleryEntry = {
789
+ keywords: ['radiobutton', 'radio button'],
790
+ id: 'radio-field',
791
+ title: 'RadioField',
792
+ importPath: '@open-mercato/ui/primitives/radio-field',
793
+ variants: [
794
+ {
795
+ id: 'default',
796
+ title: 'default',
797
+ render: () => (
798
+ <RadioGroup defaultValue="standard" aria-label="Shipping speed">
799
+ <RadioField value="standard" label="Standard" />
800
+ <RadioField value="express" label="Express" />
801
+ </RadioGroup>
802
+ ),
803
+ code: `import { RadioGroup } from '@open-mercato/ui/primitives/radio'
804
+ import { RadioField } from '@open-mercato/ui/primitives/radio-field'
805
+
806
+ <RadioGroup defaultValue="standard" aria-label="Shipping speed">
807
+ <RadioField value="standard" label="Standard" />
808
+ <RadioField value="express" label="Express" />
809
+ </RadioGroup>`,
810
+ },
811
+ {
812
+ id: 'with-description',
813
+ title: 'With description',
814
+ render: () => (
815
+ <div className="w-80">
816
+ <RadioGroup defaultValue="invoice" aria-label="Billing">
817
+ <RadioField
818
+ value="invoice"
819
+ label="Invoice"
820
+ description="Pay within 14 days of delivery."
821
+ />
822
+ <RadioField
823
+ value="prepaid"
824
+ label="Prepaid"
825
+ description="Order ships after payment clears."
826
+ />
827
+ </RadioGroup>
828
+ </div>
829
+ ),
830
+ code: `import { RadioGroup } from '@open-mercato/ui/primitives/radio'
831
+ import { RadioField } from '@open-mercato/ui/primitives/radio-field'
832
+
833
+ <RadioGroup defaultValue="invoice" aria-label="Billing">
834
+ <RadioField value="invoice" label="Invoice" description="Pay within 14 days of delivery." />
835
+ <RadioField value="prepaid" label="Prepaid" description="Order ships after payment clears." />
836
+ </RadioGroup>`,
837
+ },
838
+ ],
839
+ }
840
+
841
+ const switchEntry: GalleryEntry = {
842
+ id: 'switch',
843
+ title: 'Switch',
844
+ importPath: '@open-mercato/ui/primitives/switch',
845
+ variants: [
846
+ {
847
+ id: 'states',
848
+ title: 'States',
849
+ render: () => (
850
+ <>
851
+ <Switch aria-label="Off" />
852
+ <Switch defaultChecked aria-label="On" />
853
+ </>
854
+ ),
855
+ code: `import { Switch } from '@open-mercato/ui/primitives/switch'
856
+
857
+ <Switch />
858
+ <Switch defaultChecked />`,
859
+ },
860
+ {
861
+ id: 'disabled',
862
+ title: 'Disabled',
863
+ render: () => (
864
+ <>
865
+ <Switch disabled aria-label="Disabled off" />
866
+ <Switch disabled defaultChecked aria-label="Disabled on" />
867
+ </>
868
+ ),
869
+ code: `import { Switch } from '@open-mercato/ui/primitives/switch'
870
+
871
+ <Switch disabled />
872
+ <Switch disabled defaultChecked />`,
873
+ },
874
+ ],
875
+ }
876
+
877
+ const switchFieldEntry: GalleryEntry = {
878
+ id: 'switch-field',
879
+ title: 'SwitchField',
880
+ importPath: '@open-mercato/ui/primitives/switch-field',
881
+ variants: [
882
+ {
883
+ id: 'default',
884
+ title: 'default (switch right)',
885
+ render: () => (
886
+ <div className="w-72">
887
+ <SwitchField label="Two-factor authentication" defaultChecked />
888
+ </div>
889
+ ),
890
+ code: `import { SwitchField } from '@open-mercato/ui/primitives/switch-field'
891
+
892
+ <SwitchField label="Two-factor authentication" defaultChecked />`,
893
+ },
894
+ {
895
+ id: 'with-description',
896
+ title: 'With description',
897
+ render: () => (
898
+ <div className="w-80">
899
+ <SwitchField
900
+ label="Low-stock alerts"
901
+ description="Notify purchasing when stock drops below the reorder point."
902
+ />
903
+ </div>
904
+ ),
905
+ code: `import { SwitchField } from '@open-mercato/ui/primitives/switch-field'
906
+
907
+ <SwitchField
908
+ label="Low-stock alerts"
909
+ description="Notify purchasing when stock drops below the reorder point."
910
+ />`,
911
+ },
912
+ {
913
+ id: 'flip',
914
+ title: 'Flipped (switch left)',
915
+ render: () => (
916
+ <div className="w-72">
917
+ <SwitchField flip label="Sync inventory nightly" defaultChecked />
918
+ </div>
919
+ ),
920
+ code: `import { SwitchField } from '@open-mercato/ui/primitives/switch-field'
921
+
922
+ <SwitchField flip label="Sync inventory nightly" defaultChecked />`,
923
+ },
924
+ ],
925
+ }
926
+
927
+ const sliderEntry: GalleryEntry = {
928
+ id: 'slider',
929
+ title: 'Slider',
930
+ importPath: '@open-mercato/ui/primitives/slider',
931
+ variants: [
932
+ {
933
+ id: 'single',
934
+ title: 'Single value',
935
+ render: () => (
936
+ <div className="w-72">
937
+ <Slider defaultValue={[40]} min={0} max={100} step={5} aria-label="Discount" />
938
+ </div>
939
+ ),
940
+ code: `import { Slider } from '@open-mercato/ui/primitives/slider'
941
+
942
+ <Slider defaultValue={[40]} min={0} max={100} step={5} aria-label="Discount" />`,
943
+ },
944
+ {
945
+ id: 'range',
946
+ title: 'Range (two thumbs)',
947
+ render: () => (
948
+ <div className="w-72">
949
+ <Slider defaultValue={[20, 60]} min={0} max={100} aria-label="Price range" />
950
+ </div>
951
+ ),
952
+ code: `import { Slider } from '@open-mercato/ui/primitives/slider'
953
+
954
+ <Slider defaultValue={[20, 60]} min={0} max={100} aria-label="Price range" />`,
955
+ },
956
+ {
957
+ id: 'disabled',
958
+ title: 'Disabled',
959
+ render: () => (
960
+ <div className="w-72">
961
+ <Slider defaultValue={[45]} disabled aria-label="Disabled slider" />
962
+ </div>
963
+ ),
964
+ code: `import { Slider } from '@open-mercato/ui/primitives/slider'
965
+
966
+ <Slider defaultValue={[45]} disabled />`,
967
+ },
968
+ ],
969
+ }
970
+
971
+ const formFieldEntry: GalleryEntry = {
972
+ id: 'form-field',
973
+ title: 'FormField',
974
+ importPath: '@open-mercato/ui/primitives/form-field',
975
+ variants: [
976
+ {
977
+ id: 'default',
978
+ title: 'Label + description',
979
+ render: () => (
980
+ <div className="w-72">
981
+ <FormField label="Warehouse code" description="Short identifier used on labels.">
982
+ <Input placeholder="WAW-01" />
983
+ </FormField>
984
+ </div>
985
+ ),
986
+ code: `import { FormField } from '@open-mercato/ui/primitives/form-field'
987
+ import { Input } from '@open-mercato/ui/primitives/input'
988
+
989
+ <FormField label="Warehouse code" description="Short identifier used on labels.">
990
+ <Input placeholder="WAW-01" />
991
+ </FormField>`,
992
+ },
993
+ {
994
+ id: 'required',
995
+ title: 'Required',
996
+ render: () => (
997
+ <div className="w-72">
998
+ <FormField label="Company name" required>
999
+ <Input placeholder="Acme sp. z o.o." />
1000
+ </FormField>
1001
+ </div>
1002
+ ),
1003
+ code: `import { FormField } from '@open-mercato/ui/primitives/form-field'
1004
+ import { Input } from '@open-mercato/ui/primitives/input'
1005
+
1006
+ <FormField label="Company name" required>
1007
+ <Input placeholder="Acme sp. z o.o." />
1008
+ </FormField>`,
1009
+ },
1010
+ {
1011
+ id: 'error',
1012
+ title: 'Error',
1013
+ render: () => (
1014
+ <div className="w-72">
1015
+ <FormField label="VAT ID" error="VAT ID must have 10 digits.">
1016
+ <Input defaultValue="52601" />
1017
+ </FormField>
1018
+ </div>
1019
+ ),
1020
+ code: `import { FormField } from '@open-mercato/ui/primitives/form-field'
1021
+ import { Input } from '@open-mercato/ui/primitives/input'
1022
+
1023
+ <FormField label="VAT ID" error="VAT ID must have 10 digits.">
1024
+ <Input defaultValue="52601" />
1025
+ </FormField>`,
1026
+ },
1027
+ {
1028
+ id: 'horizontal',
1029
+ title: 'Horizontal',
1030
+ render: () => (
1031
+ <div className="w-72">
1032
+ <FormField label="Enable webhooks" orientation="horizontal">
1033
+ <Switch defaultChecked />
1034
+ </FormField>
1035
+ </div>
1036
+ ),
1037
+ code: `import { FormField } from '@open-mercato/ui/primitives/form-field'
1038
+ import { Switch } from '@open-mercato/ui/primitives/switch'
1039
+
1040
+ <FormField label="Enable webhooks" orientation="horizontal">
1041
+ <Switch defaultChecked />
1042
+ </FormField>`,
1043
+ },
1044
+ ],
1045
+ }
1046
+
1047
+ const searchInputEntry: GalleryEntry = {
1048
+ id: 'search-input',
1049
+ title: 'SearchInput',
1050
+ importPath: '@open-mercato/ui/primitives/search-input',
1051
+ variants: [
1052
+ {
1053
+ id: 'default',
1054
+ title: 'default (clearable)',
1055
+ render: () => <DemoSearchInput />,
1056
+ code: `import { SearchInput } from '@open-mercato/ui/primitives/search-input'
1057
+
1058
+ const [query, setQuery] = React.useState('')
1059
+
1060
+ <SearchInput value={query} onChange={setQuery} />`,
1061
+ },
1062
+ {
1063
+ id: 'small',
1064
+ title: 'Small',
1065
+ render: () => <DemoSearchInput size="sm" />,
1066
+ code: `import { SearchInput } from '@open-mercato/ui/primitives/search-input'
1067
+
1068
+ <SearchInput size="sm" value={query} onChange={setQuery} />`,
1069
+ },
1070
+ ],
1071
+ }
1072
+
1073
+ const emailInputEntry: GalleryEntry = {
1074
+ id: 'email-input',
1075
+ title: 'EmailInput',
1076
+ importPath: '@open-mercato/ui/primitives/email-input',
1077
+ variants: [
1078
+ {
1079
+ id: 'default',
1080
+ title: 'default',
1081
+ render: () => (
1082
+ <div className="w-72">
1083
+ <EmailInput />
1084
+ </div>
1085
+ ),
1086
+ code: `import { EmailInput } from '@open-mercato/ui/primitives/email-input'
1087
+
1088
+ <EmailInput />`,
1089
+ },
1090
+ {
1091
+ id: 'no-icon',
1092
+ title: 'Without icon',
1093
+ render: () => (
1094
+ <div className="w-72">
1095
+ <EmailInput showIcon={false} />
1096
+ </div>
1097
+ ),
1098
+ code: `import { EmailInput } from '@open-mercato/ui/primitives/email-input'
1099
+
1100
+ <EmailInput showIcon={false} />`,
1101
+ },
1102
+ {
1103
+ id: 'invalid',
1104
+ title: 'Invalid',
1105
+ render: () => (
1106
+ <div className="w-72">
1107
+ <EmailInput aria-invalid defaultValue="not-an-email" />
1108
+ </div>
1109
+ ),
1110
+ code: `import { EmailInput } from '@open-mercato/ui/primitives/email-input'
1111
+
1112
+ <EmailInput aria-invalid defaultValue="not-an-email" />`,
1113
+ },
1114
+ ],
1115
+ }
1116
+
1117
+ const passwordInputEntry: GalleryEntry = {
1118
+ id: 'password-input',
1119
+ title: 'PasswordInput',
1120
+ importPath: '@open-mercato/ui/primitives/password-input',
1121
+ variants: [
1122
+ {
1123
+ id: 'default',
1124
+ title: 'default (reveal toggle)',
1125
+ render: () => (
1126
+ <div className="w-72">
1127
+ <PasswordInput defaultValue="correct-horse-battery" autoComplete="off" />
1128
+ </div>
1129
+ ),
1130
+ code: `import { PasswordInput } from '@open-mercato/ui/primitives/password-input'
1131
+
1132
+ <PasswordInput autoComplete="current-password" />`,
1133
+ },
1134
+ {
1135
+ id: 'no-lock',
1136
+ title: 'Without lock icon',
1137
+ render: () => (
1138
+ <div className="w-72">
1139
+ <PasswordInput showLockIcon={false} autoComplete="off" />
1140
+ </div>
1141
+ ),
1142
+ code: `import { PasswordInput } from '@open-mercato/ui/primitives/password-input'
1143
+
1144
+ <PasswordInput showLockIcon={false} />`,
1145
+ },
1146
+ {
1147
+ id: 'disabled',
1148
+ title: 'Disabled',
1149
+ render: () => (
1150
+ <div className="w-72">
1151
+ <PasswordInput disabled autoComplete="off" />
1152
+ </div>
1153
+ ),
1154
+ code: `import { PasswordInput } from '@open-mercato/ui/primitives/password-input'
1155
+
1156
+ <PasswordInput disabled />`,
1157
+ },
1158
+ ],
1159
+ }
1160
+
1161
+ const websiteInputEntry: GalleryEntry = {
1162
+ id: 'website-input',
1163
+ title: 'WebsiteInput',
1164
+ importPath: '@open-mercato/ui/primitives/website-input',
1165
+ variants: [
1166
+ {
1167
+ id: 'default',
1168
+ title: 'default (https:// prefix)',
1169
+ render: () => (
1170
+ <div className="w-72">
1171
+ <WebsiteInput />
1172
+ </div>
1173
+ ),
1174
+ code: `import { WebsiteInput } from '@open-mercato/ui/primitives/website-input'
1175
+
1176
+ <WebsiteInput />`,
1177
+ },
1178
+ {
1179
+ id: 'custom-prefix',
1180
+ title: 'Custom prefix',
1181
+ render: () => (
1182
+ <div className="w-72">
1183
+ <WebsiteInput prefix="http://" />
1184
+ </div>
1185
+ ),
1186
+ code: `import { WebsiteInput } from '@open-mercato/ui/primitives/website-input'
1187
+
1188
+ <WebsiteInput prefix="http://" />`,
1189
+ },
1190
+ {
1191
+ id: 'no-prefix',
1192
+ title: 'Without prefix',
1193
+ render: () => (
1194
+ <div className="w-72">
1195
+ <WebsiteInput showPrefix={false} />
1196
+ </div>
1197
+ ),
1198
+ code: `import { WebsiteInput } from '@open-mercato/ui/primitives/website-input'
1199
+
1200
+ <WebsiteInput showPrefix={false} />`,
1201
+ },
1202
+ ],
1203
+ }
1204
+
1205
+ const amountInputEntry: GalleryEntry = {
1206
+ id: 'amount-input',
1207
+ title: 'AmountInput',
1208
+ importPath: '@open-mercato/ui/primitives/amount-input',
1209
+ variants: [
1210
+ {
1211
+ id: 'default',
1212
+ title: 'default (currency picker)',
1213
+ render: () => <DemoAmountInput />,
1214
+ code: `import { AmountInput, type AmountValue } from '@open-mercato/ui/primitives/amount-input'
1215
+
1216
+ const [value, setValue] = React.useState<AmountValue>({ amount: '', currency: 'EUR' })
1217
+
1218
+ <AmountInput value={value} onChange={setValue} />`,
1219
+ },
1220
+ {
1221
+ id: 'no-currency',
1222
+ title: 'Without currency picker',
1223
+ render: () => <DemoAmountInput showCurrency={false} />,
1224
+ code: `import { AmountInput } from '@open-mercato/ui/primitives/amount-input'
1225
+
1226
+ <AmountInput value={value} onChange={setValue} showCurrency={false} />`,
1227
+ },
1228
+ ],
1229
+ }
1230
+
1231
+ const counterInputEntry: GalleryEntry = {
1232
+ id: 'counter-input',
1233
+ title: 'CounterInput',
1234
+ importPath: '@open-mercato/ui/primitives/counter-input',
1235
+ variants: [
1236
+ {
1237
+ id: 'default',
1238
+ title: 'default',
1239
+ render: () => <DemoCounterInput min={0} max={10} />,
1240
+ code: `import { CounterInput } from '@open-mercato/ui/primitives/counter-input'
1241
+
1242
+ const [qty, setQty] = React.useState<number | null>(2)
1243
+
1244
+ <CounterInput value={qty} onChange={setQty} min={0} max={10} />`,
1245
+ },
1246
+ {
1247
+ id: 'step-precision',
1248
+ title: 'Step + precision',
1249
+ render: () => <DemoCounterInput initial={2.5} step={0.5} precision={1} min={0} />,
1250
+ code: `import { CounterInput } from '@open-mercato/ui/primitives/counter-input'
1251
+
1252
+ <CounterInput value={weight} onChange={setWeight} step={0.5} precision={1} min={0} />`,
1253
+ },
1254
+ {
1255
+ id: 'disabled',
1256
+ title: 'Disabled',
1257
+ render: () => (
1258
+ <div className="w-36">
1259
+ <CounterInput value={5} disabled />
1260
+ </div>
1261
+ ),
1262
+ code: `import { CounterInput } from '@open-mercato/ui/primitives/counter-input'
1263
+
1264
+ <CounterInput value={5} disabled />`,
1265
+ },
1266
+ ],
1267
+ }
1268
+
1269
+ const digitInputEntry: GalleryEntry = {
1270
+ id: 'digit-input',
1271
+ title: 'DigitInput',
1272
+ importPath: '@open-mercato/ui/primitives/digit-input',
1273
+ variants: [
1274
+ {
1275
+ id: 'default',
1276
+ title: 'default (6 cells)',
1277
+ render: () => <DigitInput aria-label="Verification code" />,
1278
+ code: `import { DigitInput } from '@open-mercato/ui/primitives/digit-input'
1279
+
1280
+ <DigitInput onComplete={(code) => verify(code)} />`,
1281
+ },
1282
+ {
1283
+ id: 'masked',
1284
+ title: 'Masked (4 cells)',
1285
+ render: () => <DigitInput length={4} mask value="1234" aria-label="PIN" />,
1286
+ code: `import { DigitInput } from '@open-mercato/ui/primitives/digit-input'
1287
+
1288
+ <DigitInput length={4} mask aria-label="PIN" />`,
1289
+ },
1290
+ {
1291
+ id: 'states',
1292
+ title: 'States',
1293
+ render: () => (
1294
+ <div className="flex flex-col gap-3">
1295
+ <DigitInput length={4} value="4921" aria-invalid aria-label="Invalid code" />
1296
+ <DigitInput length={4} disabled aria-label="Disabled code" />
1297
+ </div>
1298
+ ),
1299
+ code: `import { DigitInput } from '@open-mercato/ui/primitives/digit-input'
1300
+
1301
+ <DigitInput length={4} aria-invalid />
1302
+ <DigitInput length={4} disabled />`,
1303
+ },
1304
+ ],
1305
+ }
1306
+
1307
+ const cardInputEntry: GalleryEntry = {
1308
+ id: 'card-input',
1309
+ title: 'CardInput',
1310
+ importPath: '@open-mercato/ui/primitives/card-input',
1311
+ variants: [
1312
+ {
1313
+ id: 'default',
1314
+ title: 'default (empty)',
1315
+ render: () => <DemoCardInput />,
1316
+ code: `import { CardInput } from '@open-mercato/ui/primitives/card-input'
1317
+
1318
+ const [digits, setDigits] = React.useState('')
1319
+
1320
+ <CardInput value={digits} onChange={setDigits} />`,
1321
+ },
1322
+ {
1323
+ id: 'brand-detected',
1324
+ title: 'Brand detected',
1325
+ render: () => <DemoCardInput initial="4242424242424242" />,
1326
+ code: `import { CardInput } from '@open-mercato/ui/primitives/card-input'
1327
+
1328
+ <CardInput value={digits} onChange={setDigits} onBrandChange={setBrand} />`,
1329
+ },
1330
+ ],
1331
+ }
1332
+
1333
+ const buttonInputEntry: GalleryEntry = {
1334
+ id: 'button-input',
1335
+ title: 'ButtonInput',
1336
+ importPath: '@open-mercato/ui/primitives/button-input',
1337
+ variants: [
1338
+ {
1339
+ id: 'copy-link',
1340
+ title: 'Copy link',
1341
+ render: () => (
1342
+ <div className="w-80">
1343
+ <ButtonInput
1344
+ readOnly
1345
+ defaultValue="https://app.example.com/i/8f2c"
1346
+ leftIcon={<Link2 />}
1347
+ trailingAction={
1348
+ <IconButton variant="ghost" aria-label="Copy link">
1349
+ <Copy />
1350
+ </IconButton>
1351
+ }
1352
+ />
1353
+ </div>
1354
+ ),
1355
+ code: `import { Copy, Link2 } from 'lucide-react'
1356
+ import { ButtonInput } from '@open-mercato/ui/primitives/button-input'
1357
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
1358
+
1359
+ <ButtonInput
1360
+ readOnly
1361
+ defaultValue="https://app.example.com/i/8f2c"
1362
+ leftIcon={<Link2 />}
1363
+ trailingAction={
1364
+ <IconButton variant="ghost" aria-label="Copy link"><Copy /></IconButton>
1365
+ }
1366
+ />`,
1367
+ },
1368
+ {
1369
+ id: 'send',
1370
+ title: 'Send action',
1371
+ render: () => (
1372
+ <div className="w-80">
1373
+ <ButtonInput
1374
+ placeholder="Invite by email"
1375
+ trailingAction={
1376
+ <IconButton variant="ghost" aria-label="Send invite">
1377
+ <Send />
1378
+ </IconButton>
1379
+ }
1380
+ />
1381
+ </div>
1382
+ ),
1383
+ code: `import { Send } from 'lucide-react'
1384
+ import { ButtonInput } from '@open-mercato/ui/primitives/button-input'
1385
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
1386
+
1387
+ <ButtonInput
1388
+ placeholder="Invite by email"
1389
+ trailingAction={
1390
+ <IconButton variant="ghost" aria-label="Send invite"><Send /></IconButton>
1391
+ }
1392
+ />`,
1393
+ },
1394
+ ],
1395
+ }
1396
+
1397
+ const colorPickerEntry: GalleryEntry = {
1398
+ id: 'color-picker',
1399
+ title: 'ColorPicker',
1400
+ importPath: '@open-mercato/ui/primitives/color-picker',
1401
+ variants: [
1402
+ {
1403
+ id: 'default',
1404
+ title: 'default',
1405
+ render: () => <DemoColorPicker />,
1406
+ code: `import { ColorPicker } from '@open-mercato/ui/primitives/color-picker'
1407
+
1408
+ const [color, setColor] = React.useState('#6366F1')
1409
+
1410
+ <ColorPicker value={color} onChange={setColor} />`,
1411
+ },
1412
+ {
1413
+ id: 'locked-palette',
1414
+ title: 'Locked palette',
1415
+ render: () => (
1416
+ <DemoColorPicker
1417
+ allowCustom={false}
1418
+ swatches={COLOR_PICKER_DEFAULT_SWATCHES.slice(0, 5)}
1419
+ />
1420
+ ),
1421
+ code: `import { ColorPicker, COLOR_PICKER_DEFAULT_SWATCHES } from '@open-mercato/ui/primitives/color-picker'
1422
+
1423
+ <ColorPicker
1424
+ value={color}
1425
+ onChange={setColor}
1426
+ swatches={COLOR_PICKER_DEFAULT_SWATCHES.slice(0, 5)}
1427
+ allowCustom={false}
1428
+ />`,
1429
+ },
1430
+ ],
1431
+ }
1432
+
1433
+ const tagInputEntry: GalleryEntry = {
1434
+ id: 'tag-input',
1435
+ title: 'TagInput',
1436
+ importPath: '@open-mercato/ui/primitives/tag-input',
1437
+ variants: [
1438
+ {
1439
+ id: 'default',
1440
+ title: 'default',
1441
+ render: () => (
1442
+ <DemoTagInput initial={['wholesale', 'priority', 'eu']} placeholder="Add tag" />
1443
+ ),
1444
+ code: `import { TagInput } from '@open-mercato/ui/primitives/tag-input'
1445
+
1446
+ const [tags, setTags] = React.useState<string[]>(['wholesale', 'priority', 'eu'])
1447
+
1448
+ <TagInput value={tags} onChange={setTags} placeholder="Add tag" />`,
1449
+ },
1450
+ {
1451
+ id: 'max-tags',
1452
+ title: 'Max tags reached',
1453
+ render: () => (
1454
+ <DemoTagInput initial={['red', 'green', 'blue']} maxTags={3} placeholder="Add tag" />
1455
+ ),
1456
+ code: `import { TagInput } from '@open-mercato/ui/primitives/tag-input'
1457
+
1458
+ <TagInput value={tags} onChange={setTags} maxTags={3} />`,
1459
+ },
1460
+ ],
1461
+ }
1462
+
1463
+ const richEditorEntry: GalleryEntry = {
1464
+ id: 'rich-editor',
1465
+ title: 'RichEditor',
1466
+ importPath: '@open-mercato/ui/primitives/rich-editor',
1467
+ variants: [
1468
+ {
1469
+ id: 'minimal',
1470
+ title: 'minimal',
1471
+ render: () => <DemoRichEditor variant="minimal" />,
1472
+ code: `import { RichEditor } from '@open-mercato/ui/primitives/rich-editor'
1473
+
1474
+ const [html, setHtml] = React.useState('')
1475
+
1476
+ <RichEditor value={html} onChange={setHtml} variant="minimal" />`,
1477
+ },
1478
+ {
1479
+ id: 'standard',
1480
+ title: 'standard',
1481
+ render: () => <DemoRichEditor variant="standard" />,
1482
+ code: `import { RichEditor } from '@open-mercato/ui/primitives/rich-editor'
1483
+
1484
+ <RichEditor value={html} onChange={setHtml} variant="standard" />`,
1485
+ },
1486
+ ],
1487
+ }
1488
+
1489
+ export const entries: GalleryEntry[] = [
1490
+ inputEntry,
1491
+ textareaEntry,
1492
+ selectEntry,
1493
+ compactSelectEntry,
1494
+ inlineSelectEntry,
1495
+ inlineInputEntry,
1496
+ checkboxEntry,
1497
+ checkboxFieldEntry,
1498
+ radioEntry,
1499
+ radioFieldEntry,
1500
+ switchEntry,
1501
+ switchFieldEntry,
1502
+ sliderEntry,
1503
+ formFieldEntry,
1504
+ searchInputEntry,
1505
+ emailInputEntry,
1506
+ passwordInputEntry,
1507
+ websiteInputEntry,
1508
+ amountInputEntry,
1509
+ counterInputEntry,
1510
+ digitInputEntry,
1511
+ cardInputEntry,
1512
+ buttonInputEntry,
1513
+ colorPickerEntry,
1514
+ tagInputEntry,
1515
+ richEditorEntry,
1516
+ ]