@medalsocial/meda 2.8.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +130 -1
  2. package/dist/booking/add-child-sheet.d.ts +38 -0
  3. package/dist/booking/add-child-sheet.js +88 -0
  4. package/dist/booking/booking-skeleton.d.ts +24 -0
  5. package/dist/booking/booking-skeleton.js +17 -0
  6. package/dist/booking/confirmation.d.ts +85 -0
  7. package/dist/booking/confirmation.js +102 -0
  8. package/dist/booking/details-screen.d.ts +118 -0
  9. package/dist/booking/details-screen.js +314 -0
  10. package/dist/booking/format.d.ts +64 -0
  11. package/dist/booking/format.js +1 -0
  12. package/dist/booking/index.d.ts +35 -0
  13. package/dist/booking/index.js +40 -0
  14. package/dist/booking/internal/label-parts.d.ts +8 -0
  15. package/dist/booking/internal/label-parts.js +19 -0
  16. package/dist/booking/internal/ui.d.ts +33 -0
  17. package/dist/booking/internal/ui.js +35 -0
  18. package/dist/booking/label-keys.d.ts +34 -0
  19. package/dist/booking/label-keys.js +56 -0
  20. package/dist/booking/labels.d.ts +15 -0
  21. package/dist/booking/labels.js +17 -0
  22. package/dist/booking/live-status.d.ts +14 -0
  23. package/dist/booking/live-status.js +17 -0
  24. package/dist/booking/login-panel.d.ts +108 -0
  25. package/dist/booking/login-panel.js +239 -0
  26. package/dist/booking/login-sheet.d.ts +41 -0
  27. package/dist/booking/login-sheet.js +49 -0
  28. package/dist/booking/manage-screen.d.ts +113 -0
  29. package/dist/booking/manage-screen.js +369 -0
  30. package/dist/booking/otp-slots.d.ts +42 -0
  31. package/dist/booking/otp-slots.js +109 -0
  32. package/dist/booking/portal/account-card.d.ts +24 -0
  33. package/dist/booking/portal/account-card.js +18 -0
  34. package/dist/booking/portal/action-result.d.ts +30 -0
  35. package/dist/booking/portal/action-result.js +18 -0
  36. package/dist/booking/portal/age-confirm-card.d.ts +39 -0
  37. package/dist/booking/portal/age-confirm-card.js +42 -0
  38. package/dist/booking/portal/child-cards.d.ts +65 -0
  39. package/dist/booking/portal/child-cards.js +59 -0
  40. package/dist/booking/portal/data-controls.d.ts +48 -0
  41. package/dist/booking/portal/data-controls.js +103 -0
  42. package/dist/booking/portal/family-editor.d.ts +141 -0
  43. package/dist/booking/portal/family-editor.js +422 -0
  44. package/dist/booking/portal/logout-button.d.ts +21 -0
  45. package/dist/booking/portal/logout-button.js +27 -0
  46. package/dist/booking/portal/portal-shell.d.ts +71 -0
  47. package/dist/booking/portal/portal-shell.js +38 -0
  48. package/dist/booking/portal/portal-unreachable.d.ts +31 -0
  49. package/dist/booking/portal/portal-unreachable.js +19 -0
  50. package/dist/booking/portal/profile-form.d.ts +75 -0
  51. package/dist/booking/portal/profile-form.js +144 -0
  52. package/dist/booking/portal/rebook-cards.d.ts +44 -0
  53. package/dist/booking/portal/rebook-cards.js +35 -0
  54. package/dist/booking/portal/upcoming-bookings.d.ts +65 -0
  55. package/dist/booking/portal/upcoming-bookings.js +88 -0
  56. package/dist/booking/portal/vipps-link-row.d.ts +54 -0
  57. package/dist/booking/portal/vipps-link-row.js +80 -0
  58. package/dist/booking/portal/visit-history.d.ts +63 -0
  59. package/dist/booking/portal/visit-history.js +73 -0
  60. package/dist/booking/service-screen.d.ts +137 -0
  61. package/dist/booking/service-screen.js +233 -0
  62. package/dist/booking/slots.d.ts +12 -0
  63. package/dist/booking/slots.js +5 -0
  64. package/dist/booking/stylist-screen.d.ts +117 -0
  65. package/dist/booking/stylist-screen.js +226 -0
  66. package/dist/booking/summary-bar.d.ts +26 -0
  67. package/dist/booking/summary-bar.js +32 -0
  68. package/dist/booking/time-screen.d.ts +191 -0
  69. package/dist/booking/time-screen.js +418 -0
  70. package/dist/booking/types.d.ts +284 -0
  71. package/dist/booking/types.js +15 -0
  72. package/dist/booking/vipps-button.d.ts +49 -0
  73. package/dist/booking/vipps-button.js +33 -0
  74. package/dist/booking/who-screen.d.ts +121 -0
  75. package/dist/booking/who-screen.js +164 -0
  76. package/dist/primitives/avatar.d.ts +24 -0
  77. package/dist/primitives/avatar.js +44 -0
  78. package/dist/primitives/button.d.ts +21 -0
  79. package/dist/primitives/button.js +51 -0
  80. package/dist/primitives/checkbox.d.ts +23 -0
  81. package/dist/primitives/checkbox.js +20 -0
  82. package/dist/primitives/field.d.ts +47 -0
  83. package/dist/primitives/field.js +48 -0
  84. package/dist/primitives/index.d.ts +16 -0
  85. package/dist/primitives/index.js +8 -0
  86. package/dist/primitives/input.d.ts +10 -0
  87. package/dist/primitives/input.js +9 -0
  88. package/dist/primitives/sheet.d.ts +68 -0
  89. package/dist/primitives/sheet.js +303 -0
  90. package/dist/primitives/textarea.d.ts +14 -0
  91. package/dist/primitives/textarea.js +13 -0
  92. package/dist/primitives/toggle-group.d.ts +46 -0
  93. package/dist/primitives/toggle-group.js +148 -0
  94. package/dist/styles/base.css +40 -0
  95. package/dist/styles/booking.css +10 -0
  96. package/dist/styles/bridge.css +159 -0
  97. package/dist/styles/calendar.css +8 -0
  98. package/dist/styles/primitives.css +10 -0
  99. package/dist/styles/theme.css +12 -162
  100. package/dist/styles/vendor/xyflow.css +626 -0
  101. package/dist/styles/workflow-builder.css +17 -0
  102. package/package.json +45 -9
  103. package/skills/components/SKILL.md +53 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medalsocial/meda",
3
- "version": "2.8.1",
3
+ "version": "3.2.0",
4
4
  "description": "Shared Meda UI shell and runtime package.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -63,6 +63,10 @@
63
63
  "types": "./dist/calendar/index.d.ts",
64
64
  "import": "./dist/calendar/index.js"
65
65
  },
66
+ "./booking": {
67
+ "types": "./dist/booking/index.d.ts",
68
+ "default": "./dist/booking/index.js"
69
+ },
66
70
  "./workflow-builder": {
67
71
  "types": "./dist/workflow-builder/index.d.ts",
68
72
  "import": "./dist/workflow-builder/index.js"
@@ -91,6 +95,10 @@
91
95
  "types": "./dist/post-preview/index.d.ts",
92
96
  "default": "./dist/post-preview/index.js"
93
97
  },
98
+ "./primitives": {
99
+ "types": "./dist/primitives/index.d.ts",
100
+ "default": "./dist/primitives/index.js"
101
+ },
94
102
  "./styles": {
95
103
  "default": "./dist/styles/theme.css"
96
104
  },
@@ -100,6 +108,27 @@
100
108
  "./styles/tokens": {
101
109
  "default": "./dist/styles/tokens.css"
102
110
  },
111
+ "./styles/tokens.css": {
112
+ "default": "./dist/styles/tokens.css"
113
+ },
114
+ "./styles/bridge.css": {
115
+ "default": "./dist/styles/bridge.css"
116
+ },
117
+ "./styles/base.css": {
118
+ "default": "./dist/styles/base.css"
119
+ },
120
+ "./calendar/styles.css": {
121
+ "default": "./dist/styles/calendar.css"
122
+ },
123
+ "./booking/styles.css": {
124
+ "default": "./dist/styles/booking.css"
125
+ },
126
+ "./primitives/styles.css": {
127
+ "default": "./dist/styles/primitives.css"
128
+ },
129
+ "./workflow-builder/styles.css": {
130
+ "default": "./dist/styles/workflow-builder.css"
131
+ },
103
132
  "./shell/primitives": {
104
133
  "types": "./dist/shell/primitives.d.ts",
105
134
  "default": "./dist/shell/primitives.js"
@@ -136,23 +165,24 @@
136
165
  "react-dom": ">=19",
137
166
  "react-markdown": "^10.0.0",
138
167
  "rehype-highlight": "^7.0.0",
139
- "remark-gfm": "^4.0.0"
168
+ "remark-gfm": "^4.0.0",
169
+ "three": ">=0.160.0"
140
170
  },
141
171
  "peerDependenciesMeta": {
142
172
  "@dnd-kit/core": {
143
- "optional": false
173
+ "optional": true
144
174
  },
145
175
  "@dnd-kit/sortable": {
146
- "optional": false
176
+ "optional": true
147
177
  },
148
178
  "@dnd-kit/utilities": {
149
- "optional": false
179
+ "optional": true
150
180
  },
151
181
  "@react-three/fiber": {
152
182
  "optional": true
153
183
  },
154
184
  "@xyflow/react": {
155
- "optional": false
185
+ "optional": true
156
186
  },
157
187
  "next-themes": {
158
188
  "optional": true
@@ -165,18 +195,18 @@
165
195
  },
166
196
  "remark-gfm": {
167
197
  "optional": true
198
+ },
199
+ "three": {
200
+ "optional": true
168
201
  }
169
202
  },
170
203
  "dependencies": {
171
204
  "@base-ui/react": "1.8.0",
172
- "@fontsource-variable/geist": "5.3.0",
173
- "@fontsource-variable/geist-mono": "5.3.0",
174
205
  "class-variance-authority": "0.7.1",
175
206
  "clsx": "2.1.1",
176
207
  "cmdk": "1.1.1",
177
208
  "react-resizable-panels": "4.13.1",
178
209
  "tailwind-merge": "3.7.0",
179
- "three": "0.185.1",
180
210
  "vaul": "1.1.2"
181
211
  },
182
212
  "devDependencies": {
@@ -186,6 +216,8 @@
186
216
  "@dnd-kit/core": "6.3.1",
187
217
  "@dnd-kit/sortable": "10.0.0",
188
218
  "@dnd-kit/utilities": "3.2.2",
219
+ "@fontsource-variable/geist": "5.3.0",
220
+ "@fontsource-variable/geist-mono": "5.3.0",
189
221
  "@react-three/fiber": "9.7.0",
190
222
  "@size-limit/preset-small-lib": "13.0.3",
191
223
  "@storybook/addon-a11y": "10.6.0",
@@ -194,6 +226,7 @@
194
226
  "@storybook/addon-themes": "10.6.0",
195
227
  "@storybook/addon-vitest": "10.6.0",
196
228
  "@storybook/react-vite": "10.6.0",
229
+ "@tailwindcss/cli": "4.3.3",
197
230
  "@tailwindcss/vite": "4.3.3",
198
231
  "@tanstack/intent": "0.4.0",
199
232
  "@testing-library/jest-dom": "7.0.1",
@@ -207,6 +240,7 @@
207
240
  "@vitest/coverage-v8": "4.1.11",
208
241
  "@xyflow/react": "12.11.6",
209
242
  "chromatic": "18.9.4",
243
+ "esbuild": "0.28.2",
210
244
  "fast-check": "4.10.2",
211
245
  "husky": "9.1.7",
212
246
  "jsdom": "30.1.0",
@@ -220,6 +254,7 @@
220
254
  "size-limit": "13.0.3",
221
255
  "storybook": "10.6.0",
222
256
  "tailwindcss": "4.3.3",
257
+ "three": "0.185.1",
223
258
  "typescript": "~6.0.3",
224
259
  "vite": "8.3.0",
225
260
  "vitest": "4.1.11",
@@ -250,6 +285,7 @@
250
285
  "chromatic": "chromatic --build-script-name=storybook:build --exit-zero-on-changes",
251
286
  "size-limit": "size-limit",
252
287
  "size-limit:why": "size-limit --why",
288
+ "size:budget": "node ./scripts/size-budget.mjs",
253
289
  "version": "changeset version",
254
290
  "release": "pnpm build && changeset publish",
255
291
  "registry:validate": "node ./registry/scripts/validate-registry.mjs",
@@ -111,6 +111,59 @@ import { StatusPill } from '@medalsocial/meda';
111
111
 
112
112
  **Why solid backgrounds (not tinted):** the 11px small size needs ≥4.5:1 contrast to pass WCAG AA. Tinted backgrounds (`bg-info/15 text-info`) fail axe gates at this size. Solid `bg-info text-info-foreground` etc. always passes via the theme tokens. If you need a tinted variant, use it at `size="md"` or larger only, and verify with `vitest-axe`.
113
113
 
114
+ ## Form + sheet primitives — native elements, exported
115
+
116
+ `Checkbox`, `Field`, `Textarea` and `Sheet` ARE exported from `@medalsocial/meda` and
117
+ `@medalsocial/meda/primitives` (unlike the `src/components/ui/` adapters). They sit on
118
+ native elements so they stay small and work without JavaScript-heavy machinery:
119
+
120
+ ```tsx
121
+ import { Checkbox, Field, Input, Sheet, Textarea } from '@medalsocial/meda/primitives';
122
+
123
+ <Field>
124
+ <Field.Label htmlFor="email">E-mail</Field.Label>
125
+ <Input id="email" invalid aria-describedby="email-error" />
126
+ <Field.Error id="email-error">Enter a valid e-mail address.</Field.Error>
127
+ </Field>
128
+
129
+ <Checkbox id="terms" onCheckedChange={setAccepted} /> {/* native <input type="checkbox"> */}
130
+
131
+ <Sheet open={open} onOpenChange={setOpen} dismissible={!saving}>
132
+ <Sheet.Trigger render={<Button variant="outline" />}>Add child</Sheet.Trigger>
133
+ <Sheet.Content> {/* native <dialog>, showModal() */}
134
+ <Sheet.Title>Add child</Sheet.Title>
135
+ <Sheet.Description>Only for this booking.</Sheet.Description>
136
+ …
137
+ <Sheet.Close render={<Button variant="ghost" size="sm" />} aria-label="Close">×</Sheet.Close>
138
+ </Sheet.Content>
139
+ </Sheet>
140
+ ```
141
+
142
+ - `Field` owns no ids or state — wire `htmlFor` / `aria-describedby` yourself.
143
+ - `Sheet` is a bottom sheet on phones and a centred dialog from `md` (`side="bottom"` pins
144
+ the bottom sheet). Escape, backdrop click and `Sheet.Close` all go through `onOpenChange`;
145
+ `dismissible={false}` blocks them while a submit is in flight. Focus returns to the trigger.
146
+ - Reach for `src/components/ui/` (Base UI) only for menus, popovers and comboboxes.
147
+
148
+ ## Booking screens — `@medalsocial/meda/booking`
149
+
150
+ Presentational screens for a booking flow, extracted so every customer site renders the
151
+ same wizard / manage page / portal. Rules when editing or adding one:
152
+
153
+ - **No data access.** No `fetch`, router, storage, cookies, env, or Medal/SDK types. Data
154
+ comes in as the structural shapes in `src/booking/types.ts`; outcomes leave as callbacks
155
+ (`onPick`, `onSubmit`, `onSave(...) => Promise<SaveResult>`).
156
+ - **No copy, no clock.** Every string is a `labels` key (`'<screen>.<thing>'`, declared in
157
+ the screen's `*_LABEL_KEYS` array and rolled up in `label-keys.ts`); every date / price
158
+ goes through the `format: BookingFormat` prop — never `Date` getters or `Intl`.
159
+ - **Colours through the bridge only** (`bg-primary`, `text-muted-foreground`, …).
160
+ `pnpm lint:tokens` rejects palette colours (`bg-white`, `text-green-600`) and arbitrary
161
+ colour values in `src/booking`.
162
+ - **Override ladder:** CSS variables → `labels` → `classNames` slots → `components` card
163
+ renderers (export the default renderer). Keep all four working in tests.
164
+ - **Public repo:** no customer names, copy, URLs or data. Stories and tests use the invented
165
+ «Salong Demo» fixtures in `src/booking/__stories__/`.
166
+
114
167
  ## ui-adapters — NOT exported from the npm package
115
168
 
116
169
  shadcn-style adapters in `src/components/ui/` (`Dialog`, `DropdownMenu`, `Tooltip`, `Drawer`, `Command`, `Checkbox`, `Collapsible`) wrap `@base-ui/react`. **They are intentionally NOT exported from `@medalsocial/meda`** — meda follows the shadcn philosophy: you own the ui code.