@medalsocial/meda 3.3.0 → 3.5.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 (62) hide show
  1. package/README.md +35 -1
  2. package/dist/booking/add-child-sheet.d.ts +2 -1
  3. package/dist/booking/add-child-sheet.js +2 -1
  4. package/dist/booking/booking-skeleton.d.ts +2 -1
  5. package/dist/booking/confirmation.d.ts +2 -1
  6. package/dist/booking/confirmation.js +7 -6
  7. package/dist/booking/details-screen.d.ts +5 -1
  8. package/dist/booking/details-screen.js +13 -8
  9. package/dist/booking/index.d.ts +2 -2
  10. package/dist/booking/index.js +2 -2
  11. package/dist/booking/internal/label-parts.d.ts +36 -21
  12. package/dist/booking/internal/label-parts.js +71 -43
  13. package/dist/booking/internal/service-multi.d.ts +55 -0
  14. package/dist/booking/internal/service-multi.js +83 -0
  15. package/dist/booking/internal/visit.d.ts +13 -0
  16. package/dist/booking/internal/visit.js +10 -0
  17. package/dist/booking/label-keys.d.ts +13 -5
  18. package/dist/booking/label-keys.js +2 -1
  19. package/dist/booking/labels.d.ts +37 -8
  20. package/dist/booking/labels.js +45 -8
  21. package/dist/booking/login-panel.d.ts +3 -2
  22. package/dist/booking/login-panel.js +3 -2
  23. package/dist/booking/login-sheet.d.ts +2 -1
  24. package/dist/booking/login-sheet.js +2 -1
  25. package/dist/booking/manage-screen.d.ts +2 -1
  26. package/dist/booking/manage-screen.js +16 -11
  27. package/dist/booking/otp-slots.d.ts +2 -1
  28. package/dist/booking/otp-slots.js +2 -1
  29. package/dist/booking/portal/age-confirm-card.d.ts +2 -1
  30. package/dist/booking/portal/child-cards.d.ts +2 -1
  31. package/dist/booking/portal/data-controls.d.ts +2 -1
  32. package/dist/booking/portal/data-controls.js +3 -3
  33. package/dist/booking/portal/family-editor.d.ts +2 -1
  34. package/dist/booking/portal/family-editor.js +9 -9
  35. package/dist/booking/portal/logout-button.d.ts +2 -1
  36. package/dist/booking/portal/logout-button.js +2 -1
  37. package/dist/booking/portal/portal-shell.d.ts +2 -1
  38. package/dist/booking/portal/portal-shell.js +3 -2
  39. package/dist/booking/portal/portal-unreachable.d.ts +2 -1
  40. package/dist/booking/portal/profile-form.d.ts +2 -1
  41. package/dist/booking/portal/profile-form.js +3 -2
  42. package/dist/booking/portal/rebook-cards.d.ts +2 -1
  43. package/dist/booking/portal/rebook-cards.js +3 -2
  44. package/dist/booking/portal/upcoming-bookings.d.ts +2 -1
  45. package/dist/booking/portal/upcoming-bookings.js +3 -3
  46. package/dist/booking/portal/vipps-link-row.d.ts +2 -1
  47. package/dist/booking/portal/vipps-link-row.js +7 -6
  48. package/dist/booking/portal/visit-history.d.ts +2 -1
  49. package/dist/booking/service-screen.d.ts +78 -3
  50. package/dist/booking/service-screen.js +131 -46
  51. package/dist/booking/stylist-screen.d.ts +2 -1
  52. package/dist/booking/stylist-screen.js +7 -6
  53. package/dist/booking/summary-bar.d.ts +2 -1
  54. package/dist/booking/time-screen.d.ts +2 -1
  55. package/dist/booking/time-screen.js +42 -19
  56. package/dist/booking/types.d.ts +14 -1
  57. package/dist/booking/vipps-button.d.ts +2 -1
  58. package/dist/booking/vipps-button.js +2 -1
  59. package/dist/booking/who-screen.d.ts +2 -1
  60. package/dist/booking/who-screen.js +4 -3
  61. package/package.json +1 -1
  62. package/skills/components/SKILL.md +4 -0
@@ -1,6 +1,7 @@
1
1
  import { type ComponentType, type ReactNode } from 'react';
2
2
  import { type AddChildSheetLabels } from './add-child-sheet.js';
3
3
  import type { BookingFormat } from './format.js';
4
+ import { type BookingLabel } from './labels.js';
4
5
  import { type SlotClassNames } from './slots.js';
5
6
  import type { NewChild, SaveResult, WizardPerson } from './types.js';
6
7
  /**
@@ -35,7 +36,7 @@ import type { NewChild, SaveResult, WizardPerson } from './types.js';
35
36
  * from the sheet, grows the list by whole rows and moves nothing sideways.
36
37
  */
37
38
  export declare const WHO_SCREEN_LABEL_KEYS: readonly ["who.heading", "who.guest.groupLabel", "who.guest.children.one", "who.guest.children.other", "who.guest.adult", "who.guest.addedList", "who.family.legend", "who.family.self", "who.family.limit", "addChild.trigger", "addChild.title", "addChild.description.saved", "addChild.description.local", "addChild.name", "addChild.birthYear", "addChild.birthYearPlaceholder", "addChild.birthMonth", "addChild.birthMonthUnknown", "addChild.notes", "addChild.missing", "addChild.submit", "addChild.close"];
38
- export type WhoScreenLabels = Record<(typeof WHO_SCREEN_LABEL_KEYS)[number], string> & AddChildSheetLabels;
39
+ export type WhoScreenLabels = Record<(typeof WHO_SCREEN_LABEL_KEYS)[number], BookingLabel> & AddChildSheetLabels;
39
40
  /**
40
41
  * - `root` — the `<section>`
41
42
  * - `heading` — the `<h2>`
@@ -5,6 +5,7 @@ import { useRef } from 'react';
5
5
  import { cn } from '../lib/utils.js';
6
6
  import { ADD_CHILD_SHEET_LABEL_KEYS, AddChildSheet, } from './add-child-sheet.js';
7
7
  import { renderLabel } from './internal/label-parts.js';
8
+ import { labelText } from './labels.js';
8
9
  import { slotClass } from './slots.js';
9
10
  /**
10
11
  * The first step — who is the visit for?
@@ -85,7 +86,7 @@ export function WhoScreen({ labels, format, people, family, guestChoices, addedC
85
86
  selectedClassName: classNames?.cardSelected,
86
87
  };
87
88
  if (family === null) {
88
- return (_jsxs("section", { "aria-labelledby": HEADING_ID, className: slotClass(classNames, 'root', 'space-y-6'), children: [heading, loginRow, _jsxs("div", { className: "space-y-4", children: [_jsx(GuestChips, { choices: guestChoices, people: people, labels: labels, classNames: classNames, onChoose: onChoose }), addedChildren.length > 0 && (_jsx("ul", { "aria-label": labels['who.guest.addedList'], className: "space-y-2", children: addedChildren.map((entry, index) => (_jsx("li", { children: _jsx(PersonCard, { name: entry.person.name ?? '', line: entry.line, index: index, selected: true, disabled: false, onToggle: () => onChoose(people.filter((other) => other.key !== entry.person.key), false), ...cardClasses }) }, entry.person.key))) })), sheet(addedChildren.length >= maxPeople, false)] })] }));
89
+ return (_jsxs("section", { "aria-labelledby": HEADING_ID, className: slotClass(classNames, 'root', 'space-y-6'), children: [heading, loginRow, _jsxs("div", { className: "space-y-4", children: [_jsx(GuestChips, { choices: guestChoices, people: people, labels: labels, classNames: classNames, onChoose: onChoose }), addedChildren.length > 0 && (_jsx("ul", { "aria-label": labelText(labels['who.guest.addedList']), className: "space-y-2", children: addedChildren.map((entry, index) => (_jsx("li", { children: _jsx(PersonCard, { name: entry.person.name ?? '', line: entry.line, index: index, selected: true, disabled: false, onToggle: () => onChoose(people.filter((other) => other.key !== entry.person.key), false), ...cardClasses }) }, entry.person.key))) })), sheet(addedChildren.length >= maxPeople, false)] })] }));
89
90
  }
90
91
  // Defensively only what this picker draws: the caller clears guest seats
91
92
  // when the family appears, and a seat nobody can see must never count
@@ -134,7 +135,7 @@ function GuestChips({ choices, people, labels, classNames, onChoose, }) {
134
135
  event.preventDefault();
135
136
  refs.current[target]?.focus();
136
137
  }
137
- return (_jsx("div", { role: "radiogroup", "aria-label": labels['who.guest.groupLabel'], className: "grid grid-cols-2 gap-2 sm:grid-cols-4", children: choices.map((choice, index) => {
138
+ return (_jsx("div", { role: "radiogroup", "aria-label": labelText(labels['who.guest.groupLabel']), className: "grid grid-cols-2 gap-2 sm:grid-cols-4", children: choices.map((choice, index) => {
138
139
  const pressed = index === checked;
139
140
  return (_jsx("button", { ref: (element) => {
140
141
  refs.current[index] = element;
@@ -144,7 +145,7 @@ function GuestChips({ choices, people, labels, classNames, onChoose, }) {
144
145
  }) }));
145
146
  }
146
147
  function CheckCircle({ checked }) {
147
- return (_jsx("span", { "aria-hidden": "true", className: cn('flex size-6 shrink-0 items-center justify-center rounded-full border', checked ? 'border-primary bg-primary text-primary-foreground' : 'border-border'), children: checked && _jsx(Check, { className: "size-4" }) }));
148
+ return (_jsx("span", { "aria-hidden": "true", className: cn('flex size-6 shrink-0 items-center justify-center rounded-full border', checked ? 'border-primary bg-primary text-primary-foreground' : 'border-muted-foreground'), children: checked && _jsx(Check, { className: "size-4" }) }));
148
149
  }
149
150
  /** The default person card: an initial on a tinted avatar, the name, a line, a tick. */
150
151
  export function DefaultPersonCard({ name, line, index, selected, disabled, describedBy, onToggle, className, selectedClassName, }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medalsocial/meda",
3
- "version": "3.3.0",
3
+ "version": "3.5.0",
4
4
  "description": "Shared Meda UI shell and runtime package.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -156,6 +156,10 @@ same wizard / manage page / portal. Rules when editing or adding one:
156
156
  - **No copy, no clock.** Every string is a `labels` key (`'<screen>.<thing>'`, declared in
157
157
  the screen's `*_LABEL_KEYS` array and rolled up in `label-keys.ts`); every date / price
158
158
  goes through the `format: BookingFormat` prop — never `Date` getters or `Intl`.
159
+ - **Labels render in the pack's own pieces.** A label is `string | readonly string[]`:
160
+ render it as children through `renderLabel` (string → one text node, array → one per
161
+ element) and as text (`aria-label`, messages) through `fillLabel` / `labelText`. Never
162
+ split a string label at its `{placeholders}`; test both forms (`childNodes`).
159
163
  - **Colours through the bridge only** (`bg-primary`, `text-muted-foreground`, …).
160
164
  `pnpm lint:tokens` rejects palette colours (`bg-white`, `text-green-600`) and arbitrary
161
165
  colour values in `src/booking`.