@pathscale/ui 3.0.0 → 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 +13 -2
  2. package/dist/components/accordion/Accordion.css +24 -1
  3. package/dist/components/alert/Alert.css +11 -1
  4. package/dist/components/auth-field-group/AuthFieldGroup.css +11 -3
  5. package/dist/components/button/Button.css +37 -10
  6. package/dist/components/calendar/Calendar.generated.d.ts +19 -2
  7. package/dist/components/calendar/Calendar.generated.js +30 -23
  8. package/dist/components/calendar/index.d.ts +1 -1
  9. package/dist/components/card/Card.generated.d.ts +38 -2
  10. package/dist/components/card/Card.generated.js +99 -45
  11. package/dist/components/card/Card.interactions.d.ts +70 -0
  12. package/dist/components/card/Card.interactions.js +19 -0
  13. package/dist/components/card/index.d.ts +1 -1
  14. package/dist/components/checkbox/Checkbox.generated.d.ts +23 -2
  15. package/dist/components/checkbox/Checkbox.generated.js +14 -6
  16. package/dist/components/collapsible/Collapsible.css +17 -1
  17. package/dist/components/color-wheel-flower/ColorWheelFlower.generated.d.ts +8 -0
  18. package/dist/components/color-wheel-flower/ColorWheelFlower.generated.js +14 -1
  19. package/dist/components/color-wheel-flower/colorWheelFlowerContext.d.ts +9 -2
  20. package/dist/components/color-wheel-flower/colorWheelFlowerContext.js +2 -4
  21. package/dist/components/connection-settings/ConnectionSettings.css +76 -0
  22. package/dist/components/connection-settings/ConnectionSettings.generated.d.ts +45 -0
  23. package/dist/components/connection-settings/ConnectionSettings.generated.js +300 -0
  24. package/dist/components/connection-settings/ConnectionSettings.recipe.d.ts +54 -0
  25. package/dist/components/connection-settings/ConnectionSettings.recipe.js +111 -0
  26. package/dist/components/connection-settings/index.d.ts +2 -0
  27. package/dist/components/connection-settings/index.js +1 -0
  28. package/dist/components/date-picker/DatePicker.generated.d.ts +3 -1
  29. package/dist/components/date-picker/DatePicker.generated.js +8 -5
  30. package/dist/components/date-range-picker/DateRangePicker.generated.d.ts +3 -1
  31. package/dist/components/date-range-picker/DateRangePicker.generated.js +9 -6
  32. package/dist/components/dialog/Dialog.generated.js +17 -79
  33. package/dist/components/drawer/Drawer.a11y.d.ts +1 -3
  34. package/dist/components/drawer/Drawer.a11y.js +2 -30
  35. package/dist/components/drawer/Drawer.generated.d.ts +24 -0
  36. package/dist/components/drawer/Drawer.generated.js +65 -58
  37. package/dist/components/grid/Grid.generated.js +3 -3
  38. package/dist/components/icon/Icon.generated.d.ts +15 -0
  39. package/dist/components/icon/Icon.generated.js +11 -2
  40. package/dist/components/immersive-landing/ImmersiveLanding.css +1 -1
  41. package/dist/components/immersive-landing/components/CookieConsent.interactions.d.ts +24 -0
  42. package/dist/components/immersive-landing/components/CookieConsent.interactions.js +2 -0
  43. package/dist/components/immersive-landing/components/CookieConsent.js +52 -47
  44. package/dist/components/immersive-landing/components/FirefoxPWABanner.js +10 -10
  45. package/dist/components/immersive-landing/types.d.ts +15 -0
  46. package/dist/components/input/Input.css +5 -3
  47. package/dist/components/input/Input.generated.js +6 -3
  48. package/dist/components/language-switcher/LanguageSwitcher.generated.js +1 -1
  49. package/dist/components/live-chat/LiveChatPanel.generated.js +2 -6
  50. package/dist/components/live-chat/LiveChatPanel.interactions.d.ts +21 -0
  51. package/dist/components/live-chat/LiveChatPanel.interactions.js +10 -0
  52. package/dist/components/password-field/PasswordField.generated.d.ts +9 -1
  53. package/dist/components/password-field/PasswordField.generated.js +2 -2
  54. package/dist/components/password-field/PasswordField.interactions.d.ts +2 -2
  55. package/dist/components/password-field/PasswordField.interactions.js +2 -2
  56. package/dist/components/popover/Popover.a11y.d.ts +47 -0
  57. package/dist/components/popover/Popover.a11y.js +19 -0
  58. package/dist/components/popover/Popover.generated.d.ts +26 -0
  59. package/dist/components/popover/Popover.generated.js +119 -46
  60. package/dist/components/radio/Radio.generated.d.ts +26 -2
  61. package/dist/components/radio/Radio.generated.js +9 -5
  62. package/dist/components/range-calendar/RangeCalendar.generated.d.ts +3 -1
  63. package/dist/components/range-calendar/RangeCalendar.generated.js +4 -1
  64. package/dist/components/select/Select.generated.js +5 -0
  65. package/dist/components/slider/Slider.generated.d.ts +14 -1
  66. package/dist/components/slider/Slider.generated.js +3 -2
  67. package/dist/components/switch/Switch.css +0 -3
  68. package/dist/components/switch/Switch.generated.d.ts +23 -2
  69. package/dist/components/switch/Switch.generated.js +21 -44
  70. package/dist/components/switch/Switch.recipe.d.ts +61 -38
  71. package/dist/components/switch/Switch.recipe.js +88 -68
  72. package/dist/components/table/MobileListView.generated.js +1 -1
  73. package/dist/components/text/Text.generated.d.ts +26 -1
  74. package/dist/components/text/Text.generated.js +14 -13
  75. package/dist/components/text/Text.recipe.d.ts +17 -5
  76. package/dist/components/text/Text.recipe.js +7 -13
  77. package/dist/components/text/index.d.ts +1 -1
  78. package/dist/components/theme-color-picker/ThemeColorPicker.generated.js +1 -1
  79. package/dist/hooks/connection/createConnectionSettings.d.ts +128 -0
  80. package/dist/hooks/connection/createConnectionSettings.js +211 -0
  81. package/dist/hooks/connection/index.d.ts +2 -0
  82. package/dist/hooks/connection/index.js +1 -0
  83. package/dist/hooks/date/date.names.d.ts +107 -0
  84. package/dist/hooks/date/date.names.js +74 -0
  85. package/dist/hooks/date/date.utils.d.ts +11 -1
  86. package/dist/hooks/date/date.utils.js +3 -6
  87. package/dist/hooks/date/index.d.ts +1 -0
  88. package/dist/hooks/date/index.js +1 -0
  89. package/dist/hooks/date/useCalendarState.d.ts +12 -5
  90. package/dist/hooks/date/useCalendarState.js +7 -19
  91. package/dist/hooks/form/createForm.d.ts +4 -4
  92. package/dist/hooks/form/createForm.js +7 -9
  93. package/dist/index.d.ts +8 -4
  94. package/dist/index.js +3 -1
  95. package/dist/layouts.manifest.json +4 -1
  96. package/dist/lib/focus.d.ts +31 -0
  97. package/dist/lib/focus.js +39 -0
  98. package/dist/lib/overlay.d.ts +94 -0
  99. package/dist/lib/overlay.js +72 -0
  100. package/dist/purge-manifest.json +14427 -15269
  101. package/dist/responsive-classes.txt +450 -0
  102. package/dist/styles/base/index.css +42 -0
  103. package/package.json +11 -6
package/README.md CHANGED
@@ -28,7 +28,7 @@ yarn add @pathscale/ui solid-layouts && yarn add -D rsbuild-plugin-solid-layouts
28
28
 
29
29
  ## Setup
30
30
 
31
- `@pathscale/ui` 2.x is a compiled Layout bundle. Configure the application compiler before
31
+ `@pathscale/ui` 3.x is a compiled Layout bundle. Configure the application compiler before
32
32
  Solid transforms JSX:
33
33
 
34
34
  ```ts
@@ -58,11 +58,22 @@ import "@pathscale/ui/index.css";
58
58
 
59
59
  export const Example = () => (
60
60
  <Flex direction="col" gap="sm">
61
- <Button variant="primary" size="md">Primary</Button>
61
+ <Button variant="solid" flavor="primary" size="md">Primary</Button>
62
62
  </Flex>
63
63
  );
64
64
  ```
65
65
 
66
+ In the application's Tailwind v4 stylesheet, register the package as a source
67
+ (adjust the relative path from that stylesheet):
68
+
69
+ ```css
70
+ @source "../node_modules/@pathscale/ui";
71
+ ```
72
+
73
+ This includes the published `dist/responsive-classes.txt` scanner input. Grid and
74
+ Flex compose responsive classes at runtime, so scanning only the compiled JavaScript
75
+ misses utilities such as `md:grid-cols-3`.
76
+
66
77
  ## Theming
67
78
 
68
79
  Two themes ship with the library: `light` (the default when no attribute is set) and `dark`.
@@ -93,19 +93,42 @@
93
93
  transform: rotate(-180deg);
94
94
  }
95
95
 
96
+ /*
97
+ * A closed panel is out of the page, not merely flattened.
98
+ *
99
+ * `keepMounted` is the default, so a closed panel stays in the document, and
100
+ * it carried `aria-hidden="true"` while its contents kept `visibility:
101
+ * visible`. Nothing under `grid-template-rows: 0fr` and `opacity: 0` is
102
+ * display:none, so every link and button inside a closed panel was still in
103
+ * the tab order: Tab moved focus into a panel nobody can see, into an
104
+ * `aria-hidden` subtree, which is the one thing `aria-hidden` must never
105
+ * contain.
106
+ *
107
+ * `visibility: hidden` is what takes the descendants out of both the tab
108
+ * order and the accessibility tree, and it is delayed by the length of the
109
+ * collapse so the animation still plays before the panel disappears. Opening
110
+ * drops the delay, so the panel is visible for the whole of the expansion.
111
+ */
96
112
  .accordion__content {
97
113
  display: grid;
98
114
  grid-template-rows: 0fr;
99
115
  opacity: 0;
100
116
  overflow: hidden;
117
+ visibility: hidden;
101
118
  transition:
102
119
  grid-template-rows 200ms ease,
103
- opacity 200ms ease;
120
+ opacity 200ms ease,
121
+ visibility 0s linear 200ms;
104
122
  }
105
123
 
106
124
  .accordion__content--expanded {
107
125
  grid-template-rows: 1fr;
108
126
  opacity: 1;
127
+ visibility: visible;
128
+ transition:
129
+ grid-template-rows 200ms ease,
130
+ opacity 200ms ease,
131
+ visibility 0s linear 0s;
109
132
  }
110
133
 
111
134
  .accordion__body {
@@ -5,6 +5,14 @@
5
5
  * Same shape as Button: flavor or state picks --alert-accent and the
6
6
  * variant decides how it is spent. State is declared second so it wins on
7
7
  * source order — a reported condition outranks a styling preference.
8
+ *
9
+ * --alert-accent-ink carries the same split Button needed: the accent as a
10
+ * surface and the accent as ink are not the same colour when the flavor is
11
+ * `neutral`, whose accent is --color-base-300, the page one step darker.
12
+ * `plain` is the variant that writes the accent straight onto the page, so
13
+ * `variant="plain" flavor="neutral"` was unreadable for exactly the reason a
14
+ * neutral outline Button was invisible. Ink defaults to the accent, so only
15
+ * `neutral` overrides it.
8
16
  * --------------------------------------------------------------------- */
9
17
  .alert {
10
18
  display: flex;
@@ -20,6 +28,7 @@
20
28
 
21
29
  --alert-accent: var(--color-base-300);
22
30
  --alert-accent-fg: var(--color-base-content);
31
+ --alert-accent-ink: var(--alert-accent);
23
32
  --alert-bg: var(--color-base-200);
24
33
  --alert-fg: var(--color-base-content);
25
34
  --alert-border: transparent;
@@ -33,6 +42,7 @@
33
42
  .alert--flavor-neutral {
34
43
  --alert-accent: var(--color-base-300);
35
44
  --alert-accent-fg: var(--color-base-content);
45
+ --alert-accent-ink: var(--color-base-content);
36
46
  }
37
47
  .alert--flavor-primary {
38
48
  --alert-accent: var(--color-primary);
@@ -96,7 +106,7 @@
96
106
 
97
107
  .alert--plain {
98
108
  --alert-bg: transparent;
99
- --alert-fg: var(--alert-accent);
109
+ --alert-fg: var(--alert-accent-ink);
100
110
  --alert-border: transparent;
101
111
  padding: 0;
102
112
  }
@@ -5,15 +5,23 @@
5
5
  flex-direction: column;
6
6
  }
7
7
 
8
+ /*
9
+ * The same three gaps `Flex` names.
10
+ *
11
+ * `md` and `lg` already matched `gap-4` and `gap-6`; `sm` was 0.75rem where
12
+ * Flex's is 0.5rem. One name meaning two spacings is the kind of thing an
13
+ * application fixes with a corrective class once per form, forever -- and it
14
+ * is the same defect `--control-h-*` was added for, one axis over.
15
+ */
8
16
  .auth-field-group--sm {
9
- gap: 0.75rem;
17
+ gap: var(--gap-sm);
10
18
  }
11
19
 
12
20
  .auth-field-group--md {
13
- gap: 1rem;
21
+ gap: var(--gap-md);
14
22
  }
15
23
 
16
24
  .auth-field-group--lg {
17
- gap: 1.5rem;
25
+ gap: var(--gap-lg);
18
26
  }
19
27
  }
@@ -2,10 +2,31 @@
2
2
  /* -----------------------------------------------------------------------
3
3
  * Root
4
4
  *
5
- * Two custom properties carry the whole state x variant cross product:
5
+ * Three custom properties carry the whole state x variant cross product:
6
6
  * a state sets --button-accent (and its readable foreground), and a variant
7
7
  * decides how that accent is spent. 8 states + 5 variants = 13 rules
8
8
  * instead of 40 combinations.
9
+ *
10
+ * The third is --button-accent-ink, and it exists because the accent is two
11
+ * different things depending on how a variant spends it. `solid` paints the
12
+ * accent as a *surface* and writes on it with --button-accent-fg; `outline`,
13
+ * `soft` and `plain` paint the accent as *ink*, on the page's own surface.
14
+ * Seven flavors set an accent that works either way. `neutral` sets
15
+ * --color-base-300, which is a surface token by construction: it is the page
16
+ * one step darker.
17
+ *
18
+ * So `variant="outline" flavor="neutral"` resolved label and border alike to
19
+ * base-300 and rendered a completely invisible control: correct role, correct
20
+ * name, correct 46x28 box, clickable, and 0 of its 1288 pixels different from
21
+ * the background behind it. Measured at #e6e4e3 on a #f5f5f4 page, the label
22
+ * was at 1.16:1. The focus ring had the same fault for the same reason: a
23
+ * neutral button's focus ring was drawn in the surface colour.
24
+ *
25
+ * --button-accent-ink is therefore what the accent means when it is ink. It
26
+ * defaults to the accent, so the seven flavors that already worked are
27
+ * untouched and a theme defining its own flavor needs to set nothing; only
28
+ * `neutral` overrides it, to the content colour that is readable on the page
29
+ * by definition.
9
30
  * --------------------------------------------------------------------- */
10
31
  .button {
11
32
  position: relative;
@@ -36,6 +57,7 @@
36
57
 
37
58
  --button-accent: var(--color-base-300);
38
59
  --button-accent-fg: var(--color-base-content);
60
+ --button-accent-ink: var(--button-accent);
39
61
  --button-bg: transparent;
40
62
  --button-bg-hover: var(--button-bg);
41
63
  --button-bg-pressed: var(--button-bg-hover);
@@ -49,7 +71,7 @@
49
71
 
50
72
  .button:focus-visible,
51
73
  .button[data-focus-visible="true"] {
52
- outline: var(--focus-ring-width, 2px) solid var(--button-accent);
74
+ outline: var(--focus-ring-width, 2px) solid var(--button-accent-ink);
53
75
  outline-offset: var(--focus-ring-offset, 2px);
54
76
  }
55
77
 
@@ -84,9 +106,14 @@
84
106
  /* -----------------------------------------------------------------------
85
107
  * Flavor — a styling preference: which palette slot to wear
86
108
  * --------------------------------------------------------------------- */
109
+ /*
110
+ * The one flavor whose accent is a surface. `outline`, `soft` and `plain`
111
+ * would otherwise draw the label in it, on the page it is one step away from.
112
+ */
87
113
  .button--flavor-neutral {
88
114
  --button-accent: var(--color-base-300);
89
115
  --button-accent-fg: var(--color-base-content);
116
+ --button-accent-ink: var(--color-base-content);
90
117
  }
91
118
  .button--flavor-primary {
92
119
  --button-accent: var(--color-primary);
@@ -177,7 +204,7 @@
177
204
  var(--button-accent),
178
205
  var(--color-base-100) 74%
179
206
  );
180
- --button-fg: var(--button-accent);
207
+ --button-fg: var(--button-accent-ink);
181
208
  --button-border: transparent;
182
209
  }
183
210
 
@@ -193,8 +220,8 @@
193
220
  var(--button-accent),
194
221
  transparent 80%
195
222
  );
196
- --button-fg: var(--button-accent);
197
- --button-border: var(--button-accent);
223
+ --button-fg: var(--button-accent-ink);
224
+ --button-border: var(--button-accent-ink);
198
225
  }
199
226
 
200
227
  /* Ghost keeps body text colour: it is chrome, not an accent surface. */
@@ -210,7 +237,7 @@
210
237
  --button-bg: transparent;
211
238
  --button-bg-hover: transparent;
212
239
  --button-bg-pressed: transparent;
213
- --button-fg: var(--button-accent);
240
+ --button-fg: var(--button-accent-ink);
214
241
  --button-border: transparent;
215
242
  height: auto;
216
243
  padding-inline: 0;
@@ -225,20 +252,20 @@
225
252
  * Size
226
253
  * --------------------------------------------------------------------- */
227
254
  .button--xs {
228
- height: 1.75rem;
255
+ height: var(--control-h-xs);
229
256
  padding-inline: 0.5rem;
230
257
  font-size: 0.75rem;
231
258
  }
232
259
  .button--sm {
233
- height: 2.25rem;
260
+ height: var(--control-h-sm);
234
261
  padding-inline: 0.75rem;
235
262
  }
236
263
  .button--md {
237
- height: 2.5rem;
264
+ height: var(--control-h-md);
238
265
  padding-inline: 1rem;
239
266
  }
240
267
  .button--lg {
241
- height: 2.75rem;
268
+ height: var(--control-h-lg);
242
269
  padding-inline: 1.125rem;
243
270
  font-size: 1rem;
244
271
  }
@@ -1,10 +1,10 @@
1
1
  import type { Component as __LayoutComponent } from "solid-js";
2
2
  import "./Calendar.css";
3
3
  import type { JSX } from "@solidjs/web";
4
- import { type CalendarSelectionMode } from "../../hooks/date";
4
+ import { type CalendarSelectionMode, type DateNames } from "../../hooks/date";
5
5
  import type { UIBaseProps, State } from "../vocabulary";
6
6
  export type CalendarWeekdayFormat = "narrow" | "short" | "long";
7
- export type { CalendarSelectionMode };
7
+ export type { CalendarSelectionMode, DateNames };
8
8
  export type CalendarDaySelectHandler = (date: Date) => void;
9
9
  export type CalendarDayHoverHandler = (date?: Date) => void;
10
10
  type CalendarBaseProps = {
@@ -20,7 +20,24 @@ type CalendarBaseProps = {
20
20
  minValue?: Date;
21
21
  maxValue?: Date;
22
22
  isDateUnavailable?: (date: Date) => boolean;
23
+ /**
24
+ * The language to render in. Honoured only when `dateNames` supplies the
25
+ * names to back it; on its own it cannot change what is on screen, because
26
+ * the library carries no locale data beyond `en-US`. Whatever is actually
27
+ * rendered is reported on the root element's `lang`.
28
+ */
23
29
  locale?: string;
30
+ /**
31
+ * Month and weekday names for a language other than English.
32
+ *
33
+ * The library ships one table, `en-US`, and no way to derive another: `Intl`
34
+ * is unavailable in the chuzz browser and ICU data is deliberately not
35
+ * shipped. A translated site passes its own names here, from the same i18n
36
+ * catalogue it already uses for the rest of its strings. All five arrays are
37
+ * required. Omit this and the calendar renders English and says `lang="en-US"`
38
+ * regardless of `locale`.
39
+ */
40
+ dateNames?: DateNames;
24
41
  weekdayFormat?: CalendarWeekdayFormat;
25
42
  showOutsideDays?: boolean;
26
43
  state?: State;
@@ -3,11 +3,11 @@ import { defineComponent } from "solid-layouts/solid-2/application-boundary";
3
3
  import "./Calendar.css";
4
4
  import { For, Show, createMemo, createTrackedEffect, createUniqueId, omit } from "solid-js";
5
5
  import { twMerge } from "../../lib/twMerge.js";
6
- import { DAYS_PER_WEEK, addDays, compareDates, getToday, normalizeDate, parseDate, shiftDateByMonths, toISODate, useCalendarNavigation, useCalendarState, useDateSelection } from "../../hooks/date/index.js";
6
+ import { DAYS_PER_WEEK, addDays, compareDates, getToday, normalizeDate, parseDate, resolveDateNames, shiftDateByMonths, toISODate, useCalendarNavigation, useCalendarState, useDateSelection } from "../../hooks/date/index.js";
7
7
  import { CLASSES, componentRecipe } from "./Calendar.recipe.js";
8
8
  var _tmpl$ = /*#__PURE__*/ template('<div><div><div><button><svg><path d="m15 18-6-6 6-6"></path></svg></button></div><div></div><div><button><svg><path d="m9 18 6-6-6-6"></path></svg></button></div></div><div><div><div></div></div><div>'), _tmpl$2 = /*#__PURE__*/ template("<span>"), _tmpl$3 = /*#__PURE__*/ template("<div>"), _tmpl$4 = /*#__PURE__*/ template("<button><span>");
9
9
  const __solidLayoutCalendar = (_stable, p)=>{
10
- const others = omit(p, "class", "dataTheme", "style", "ref", "selectionMode", "value", "defaultValue", "onChange", "rangeStart", "rangeEnd", "rangePreview", "onDaySelect", "onDayHover", "minValue", "maxValue", "isDateUnavailable", "locale", "weekdayFormat", "showOutsideDays", "state", "disabled");
10
+ const others = omit(p, "class", "dataTheme", "style", "ref", "selectionMode", "value", "defaultValue", "onChange", "rangeStart", "rangeEnd", "rangePreview", "onDaySelect", "onDayHover", "minValue", "maxValue", "isDateUnavailable", "locale", "dateNames", "weekdayFormat", "showOutsideDays", "state", "disabled");
11
11
  const selectionMode = createMemo(()=>p.selectionMode ?? "single");
12
12
  const dateSelection = useDateSelection({
13
13
  value: ()=>p.value,
@@ -22,7 +22,9 @@ const __solidLayoutCalendar = (_stable, p)=>{
22
22
  const focusReferenceDate = createMemo(()=>selectedDate() ?? rangeEnd() ?? rangeStart() ?? normalizeDate(p.value) ?? defaultReferenceDate());
23
23
  const minDate = createMemo(()=>normalizeDate(p.minValue));
24
24
  const maxDate = createMemo(()=>normalizeDate(p.maxValue));
25
- const locale = createMemo(()=>p.locale ?? "en-US");
25
+ const resolvedNames = createMemo(()=>resolveDateNames(p.locale, p.dateNames));
26
+ const dateNames = createMemo(()=>resolvedNames().names);
27
+ const renderedLocale = createMemo(()=>resolvedNames().locale);
26
28
  const weekdayFormat = createMemo(()=>p.weekdayFormat ?? "short");
27
29
  const showOutsideDays = createMemo(()=>p.showOutsideDays ?? true);
28
30
  const isCalendarDisabled = createMemo(()=>Boolean("disabled" === p.state) || Boolean(p.disabled));
@@ -46,7 +48,7 @@ const __solidLayoutCalendar = (_stable, p)=>{
46
48
  });
47
49
  const calendarState = useCalendarState({
48
50
  selectionMode: ()=>selectionMode(),
49
- locale,
51
+ dateNames,
50
52
  weekdayFormat,
51
53
  visibleMonth: navigation.visibleMonth,
52
54
  focusedDate: navigation.focusedDate,
@@ -146,6 +148,9 @@ const __solidLayoutCalendar = (_stable, p)=>{
146
148
  get ["data-disabled"] () {
147
149
  return isCalendarDisabled() ? "true" : "false";
148
150
  },
151
+ get lang () {
152
+ return renderedLocale();
153
+ },
149
154
  get ["data-theme"] () {
150
155
  return p.dataTheme;
151
156
  },
@@ -199,9 +204,11 @@ const __solidLayoutCalendar = (_stable, p)=>{
199
204
  class: CLASSES.Heading.base
200
205
  }), {
201
206
  "data-slot": "calendar-heading",
207
+ role: "heading",
208
+ "aria-level": "2",
202
209
  "aria-live": "polite"
203
210
  }), true);
204
- insert(_el$6, ()=>calendarState.monthFormatter().format(navigation.visibleMonth()));
211
+ insert(_el$6, ()=>calendarState.monthLabel());
205
212
  spread(_el$7, mergeProps(()=>({
206
213
  class: CLASSES.Nav.base
207
214
  }), {
@@ -294,7 +301,7 @@ const __solidLayoutCalendar = (_stable, p)=>{
294
301
  insert(_el$13, createComponent(For, {
295
302
  each: week,
296
303
  children: (date)=>{
297
- const cellState = calendarState.getCellState(date);
304
+ const cellState = createMemo(()=>calendarState.getCellState(date));
298
305
  const isoDate = toISODate(date);
299
306
  var _el$14 = _tmpl$3();
300
307
  spread(_el$14, mergeProps(()=>({
@@ -305,7 +312,7 @@ const __solidLayoutCalendar = (_stable, p)=>{
305
312
  }), true);
306
313
  insert(_el$14, createComponent(Show, {
307
314
  get when () {
308
- return showOutsideDays() || !cellState.isOutsideMonth;
315
+ return showOutsideDays() || !cellState().isOutsideMonth;
309
316
  },
310
317
  get fallback () {
311
318
  var _el$17 = _tmpl$2();
@@ -322,57 +329,57 @@ const __solidLayoutCalendar = (_stable, p)=>{
322
329
  spread(_el$15, mergeProps({
323
330
  type: "button"
324
331
  }, ()=>({
325
- class: twMerge(CLASSES.Cell.base, cellState.isSelected && CLASSES.Cell.flag.selected, cellState.isRangeStart && CLASSES.Cell.flag.rangeStart, cellState.isRangeEnd && CLASSES.Cell.flag.rangeEnd, cellState.isInCommittedRange && CLASSES.Cell.flag.inRange, cellState.isInPreviewRange && !cellState.isInCommittedRange && CLASSES.Cell.flag.inPreviewRange, cellState.isToday && CLASSES.Cell.flag.today, cellState.isOutsideMonth && CLASSES.Cell.flag.outsideMonth, cellState.isDisabled && CLASSES.Cell.flag.disabled, cellState.isUnavailable && CLASSES.Cell.flag.unavailable, cellState.isFocused && CLASSES.Cell.flag.focused)
332
+ class: twMerge(CLASSES.Cell.base, cellState().isSelected && CLASSES.Cell.flag.selected, cellState().isRangeStart && CLASSES.Cell.flag.rangeStart, cellState().isRangeEnd && CLASSES.Cell.flag.rangeEnd, cellState().isInCommittedRange && CLASSES.Cell.flag.inRange, cellState().isInPreviewRange && !cellState().isInCommittedRange && CLASSES.Cell.flag.inPreviewRange, cellState().isToday && CLASSES.Cell.flag.today, cellState().isOutsideMonth && CLASSES.Cell.flag.outsideMonth, cellState().isDisabled && CLASSES.Cell.flag.disabled, cellState().isUnavailable && CLASSES.Cell.flag.unavailable, cellState().isFocused && CLASSES.Cell.flag.focused)
326
333
  }), {
327
334
  "data-slot": "calendar-cell",
328
335
  "data-date": isoDate,
329
336
  get ["data-selected"] () {
330
- return cellState.isSelected ? "true" : "false";
337
+ return cellState().isSelected ? "true" : "false";
331
338
  },
332
339
  get ["data-range-start"] () {
333
- return cellState.isRangeStart ? "true" : "false";
340
+ return cellState().isRangeStart ? "true" : "false";
334
341
  },
335
342
  get ["data-range-end"] () {
336
- return cellState.isRangeEnd ? "true" : "false";
343
+ return cellState().isRangeEnd ? "true" : "false";
337
344
  },
338
345
  get ["data-in-range"] () {
339
- return cellState.isInCommittedRange ? "true" : "false";
346
+ return cellState().isInCommittedRange ? "true" : "false";
340
347
  },
341
348
  get ["data-in-preview-range"] () {
342
- return cellState.isInPreviewRange ? "true" : "false";
349
+ return cellState().isInPreviewRange ? "true" : "false";
343
350
  },
344
351
  get ["data-today"] () {
345
- return cellState.isToday ? "true" : "false";
352
+ return cellState().isToday ? "true" : "false";
346
353
  },
347
354
  get ["data-outside-month"] () {
348
- return cellState.isOutsideMonth ? "true" : "false";
355
+ return cellState().isOutsideMonth ? "true" : "false";
349
356
  },
350
357
  get ["data-disabled"] () {
351
- return cellState.isDisabled ? "true" : "false";
358
+ return cellState().isDisabled ? "true" : "false";
352
359
  },
353
360
  get ["data-unavailable"] () {
354
- return cellState.isUnavailable ? "true" : "false";
361
+ return cellState().isUnavailable ? "true" : "false";
355
362
  },
356
363
  role: "gridcell",
357
364
  get ["aria-label"] () {
358
- return calendarState.dayLabelFormatter().format(date);
365
+ return calendarState.formatDayLabel(date);
359
366
  },
360
367
  get ["aria-selected"] () {
361
- return cellState.isAriaSelected ? "true" : "false";
368
+ return cellState().isAriaSelected ? "true" : "false";
362
369
  },
363
370
  get ["aria-disabled"] () {
364
- return cellState.isDisabled ? "true" : "false";
371
+ return cellState().isDisabled ? "true" : "false";
365
372
  },
366
373
  get disabled () {
367
- return cellState.isDisabled;
374
+ return cellState().isDisabled;
368
375
  },
369
376
  get tabindex () {
370
- return cellState.isFocused ? 0 : -1;
377
+ return cellState().isFocused ? 0 : -1;
371
378
  },
372
379
  onClick: ()=>selectDate(date),
373
380
  onFocus: ()=>navigation.setFocusedDate(date),
374
381
  onMouseEnter: ()=>{
375
- if (cellState.isDisabled) return;
382
+ if (cellState().isDisabled) return;
376
383
  p.onDayHover?.(date);
377
384
  },
378
385
  onKeyDown: handleCellKeyDown
@@ -1 +1 @@
1
- export { type CalendarDayHoverHandler, type CalendarDaySelectHandler, type CalendarProps, type CalendarSelectionMode, type CalendarWeekdayFormat, default, } from "./Calendar.generated";
1
+ export { type CalendarDayHoverHandler, type CalendarDaySelectHandler, type CalendarProps, type CalendarSelectionMode, type CalendarWeekdayFormat, type DateNames, default, } from "./Calendar.generated";
@@ -2,7 +2,7 @@ import type { Component as __LayoutComponent } from "solid-js";
2
2
  import "../_shared/material.css";
3
3
  import type { JSX } from "@solidjs/web";
4
4
  import "./Card.css";
5
- import type { Flavor, Material, Radius, Space, State, UIBaseProps, Variant } from "../vocabulary";
5
+ import type { Flavor, Material, Radius, Space, UIBaseProps, Variant } from "../vocabulary";
6
6
  /**
7
7
  * @deprecated Use `Material` from the shared vocabulary. Kept as an alias
8
8
  * because it is exported publicly and removing it would break call sites; it
@@ -10,16 +10,52 @@ import type { Flavor, Material, Radius, Space, State, UIBaseProps, Variant } fro
10
10
  */
11
11
  export type CardMaterial = Material;
12
12
  export type CardElevation = "none" | "sm" | "md" | "lg";
13
+ /**
14
+ * The states this card actually renders.
15
+ *
16
+ * Not the shared `State`, which is what the prop was typed as. That union is
17
+ * `default | loading | error | invalid | disabled | hidden` and this recipe
18
+ * implements `info | success | warning | danger`: the two have **no member in
19
+ * common**. So every value the type permitted resolved to no class, and every
20
+ * value the recipe implements was a type error.
21
+ *
22
+ * A prop that accepts only values it ignores is worse than one that does not
23
+ * exist, because it reads as configured. Narrowed to what is implemented;
24
+ * `state="disabled"` and friends stop type-checking, and they never did
25
+ * anything, so nothing that worked stops working.
26
+ *
27
+ * A card is not a form control, which is why the shared vocabulary does not
28
+ * fit: it has no validity and nothing to disable. Behaviour lives on
29
+ * `isInteractive`.
30
+ */
31
+ export type CardState = "info" | "success" | "warning" | "danger";
13
32
  export type CardProps = Omit<JSX.HTMLAttributes<HTMLDivElement>, "children"> & UIBaseProps & {
14
33
  variant?: Variant;
15
34
  material?: Material;
16
35
  elevation?: CardElevation;
17
36
  flavor?: Flavor;
18
- state?: State;
37
+ state?: CardState;
19
38
  padding?: Space;
20
39
  radius?: Radius;
21
40
  /** Replaces isHoverable and isPressable, which had one call site each across 330. */
22
41
  isInteractive?: boolean;
42
+ /**
43
+ * Renders the card as an anchor, and navigates.
44
+ *
45
+ * A whole card that navigates is the common shape, and the way it was
46
+ * written was `<a href><Card isInteractive /></a>`, which put a `button`
47
+ * inside a `link` with the same name and the same box. That is invalid
48
+ * HTML, it announces the card twice, and a press by coordinate lands on
49
+ * whichever of the two happens to be on top.
50
+ *
51
+ * A card that navigates should be the anchor rather than sit inside one,
52
+ * which is what `Button` already does. Middle-click, right-click,
53
+ * open-in-new-tab and "copy link address" all work, which a `div` with a
54
+ * click handler takes away.
55
+ */
56
+ href?: string;
57
+ target?: JSX.AnchorHTMLAttributes<HTMLAnchorElement>["target"];
58
+ rel?: string;
23
59
  header?: JSX.Element;
24
60
  footer?: JSX.Element;
25
61
  children: JSX.Element;