@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
@@ -0,0 +1,211 @@
1
+ import { createEffect, createRoot, createSignal } from "solid-js";
2
+ const ABSOLUTE_URL = /^[a-z][a-z0-9+.-]*:\/\/(\[[^\]\s]*\]|[^\s/?#:]+)(?::(\d{1,5}))?(?:[/?#]\S*)?$/i;
3
+ const IPV6_GROUP = "[0-9a-f]{1,4}";
4
+ const IPV4_TAIL = "(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)";
5
+ const IPV6_FULL = new RegExp(`^(?:${IPV6_GROUP}:){6}(?:${IPV6_GROUP}:${IPV6_GROUP}|${IPV4_TAIL})$`, "i");
6
+ const IPV6_PIECES = new RegExp(`^(?:${IPV6_GROUP}(?::${IPV6_GROUP})*)?$`, "i");
7
+ const isIpv6Literal = (host)=>{
8
+ if (IPV6_FULL.test(host)) return true;
9
+ const halves = host.split("::");
10
+ if (2 !== halves.length) return false;
11
+ const [head, tail] = halves;
12
+ const embeddedV4 = new RegExp(`(?:^|:)(${IPV4_TAIL})$`, "i").exec(tail);
13
+ const groups = embeddedV4 ? tail.slice(0, tail.length - embeddedV4[1].length).replace(/:$/, "") : tail;
14
+ if (!IPV6_PIECES.test(head)) return false;
15
+ if (!IPV6_PIECES.test(groups)) return false;
16
+ const count = (part)=>"" === part ? 0 : part.split(":").length;
17
+ return count(head) + count(groups) + (embeddedV4 ? 2 : 0) <= 7;
18
+ };
19
+ const isAbsoluteUrl = (url)=>{
20
+ const match = ABSOLUTE_URL.exec(url);
21
+ if (!match) return `${url} is not an absolute address (expected scheme://host)`;
22
+ const [, host, port] = match;
23
+ if (host.startsWith("[") && !isIpv6Literal(host.slice(1, -1))) return `${url} does not contain a valid IPv6 address`;
24
+ if (void 0 !== port && Number(port) > 65535) return `${url} has a port outside 0-65535`;
25
+ };
26
+ const isRecord = (value)=>"object" == typeof value && null !== value && !Array.isArray(value);
27
+ const createConnectionSettings = (options)=>{
28
+ const { storageKey, endpoints, appPublicId = "", onApply } = options;
29
+ const fallbacks = Object.freeze(Object.fromEntries(endpoints.map((e)=>[
30
+ e.name,
31
+ e.fallback
32
+ ])));
33
+ const defaults = ()=>({
34
+ overrides: {},
35
+ urls: Object.fromEntries(endpoints.map((e)=>[
36
+ e.name,
37
+ e.fallback
38
+ ])),
39
+ appPublicId
40
+ });
41
+ const read = ()=>{
42
+ const base = defaults();
43
+ try {
44
+ if ("u" < typeof localStorage) return base;
45
+ const raw = localStorage.getItem(storageKey);
46
+ if (!raw) return base;
47
+ const parsed = JSON.parse(raw);
48
+ if (!isRecord(parsed)) return base;
49
+ const overrides = {};
50
+ const urls = {
51
+ ...base.urls
52
+ };
53
+ const storedOverrides = isRecord(parsed.overrides) ? parsed.overrides : {};
54
+ const storedUrls = isRecord(parsed.urls) ? parsed.urls : {};
55
+ for (const endpoint of endpoints){
56
+ const url = storedUrls[endpoint.name];
57
+ const usable = "string" == typeof url && "" !== url && void 0 === (endpoint.validate ?? isAbsoluteUrl)(url);
58
+ if (usable) urls[endpoint.name] = url;
59
+ if (usable && true === storedOverrides[endpoint.name]) overrides[endpoint.name] = true;
60
+ }
61
+ return {
62
+ overrides,
63
+ urls,
64
+ appPublicId: "string" == typeof parsed.appPublicId ? parsed.appPublicId : base.appPublicId
65
+ };
66
+ } catch {
67
+ return base;
68
+ }
69
+ };
70
+ const [state, setState, isApplying, setIsApplying] = createRoot(()=>{
71
+ const [s, setS] = createSignal(read());
72
+ const [a, setA] = createSignal(false);
73
+ return [
74
+ s,
75
+ setS,
76
+ a,
77
+ setA
78
+ ];
79
+ });
80
+ const atDefaults = (value)=>value.appPublicId === appPublicId && endpoints.every((e)=>true !== value.overrides[e.name] && value.urls[e.name] === e.fallback);
81
+ const write = (value)=>{
82
+ try {
83
+ if ("u" < typeof localStorage) return;
84
+ if (atDefaults(value)) localStorage.removeItem(storageKey);
85
+ else localStorage.setItem(storageKey, JSON.stringify(value));
86
+ } catch {}
87
+ };
88
+ createRoot(()=>{
89
+ createEffect(()=>state(), (value)=>{
90
+ write(value);
91
+ });
92
+ });
93
+ let committed = state();
94
+ let inFlight = 0;
95
+ let queue = Promise.resolve();
96
+ const update = (change)=>{
97
+ committed = change(committed);
98
+ setState(committed);
99
+ };
100
+ const resolveFrom = (current)=>Object.fromEntries(endpoints.map((e)=>{
101
+ const override = true === current.overrides[e.name] ? current.urls[e.name] : void 0;
102
+ return [
103
+ e.name,
104
+ override && "" !== override ? override : e.fallback
105
+ ];
106
+ }));
107
+ let resolvedFor;
108
+ let resolvedValue = Object.freeze({});
109
+ const resolved = ()=>{
110
+ const current = state();
111
+ if (resolvedFor !== current) {
112
+ resolvedFor = current;
113
+ resolvedValue = Object.freeze(resolveFrom(current));
114
+ }
115
+ return resolvedValue;
116
+ };
117
+ return {
118
+ get state () {
119
+ return state();
120
+ },
121
+ get urls () {
122
+ return resolved();
123
+ },
124
+ validate (name, url) {
125
+ const endpoint = endpoints.find((e)=>e.name === name);
126
+ if (!endpoint) return `${name} is not a configured endpoint`;
127
+ if ("" === url) return "an address is required";
128
+ return (endpoint.validate ?? isAbsoluteUrl)(url);
129
+ },
130
+ get fallbacks () {
131
+ return fallbacks;
132
+ },
133
+ get isApplying () {
134
+ return isApplying();
135
+ },
136
+ get isAtDefaults () {
137
+ state();
138
+ return atDefaults(committed);
139
+ },
140
+ state$: state,
141
+ isOverridden (name) {
142
+ return true === state().overrides[name];
143
+ },
144
+ setUrl (name, url) {
145
+ if ("" !== url) {
146
+ const endpoint = endpoints.find((e)=>e.name === name);
147
+ const problem = endpoint ? (endpoint.validate ?? isAbsoluteUrl)(url) : `${name} is not a configured endpoint`;
148
+ if (problem) return problem;
149
+ }
150
+ update((c)=>({
151
+ ...c,
152
+ urls: {
153
+ ...c.urls,
154
+ [name]: url
155
+ }
156
+ }));
157
+ },
158
+ setOverride (name, on) {
159
+ update((c)=>({
160
+ ...c,
161
+ overrides: {
162
+ ...c.overrides,
163
+ [name]: on
164
+ }
165
+ }));
166
+ },
167
+ setUseCustom (on) {
168
+ update((c)=>({
169
+ ...c,
170
+ overrides: Object.fromEntries(endpoints.map((e)=>[
171
+ e.name,
172
+ on
173
+ ]))
174
+ }));
175
+ },
176
+ setAppPublicId (id) {
177
+ update((c)=>({
178
+ ...c,
179
+ appPublicId: id
180
+ }));
181
+ },
182
+ reset () {
183
+ committed = defaults();
184
+ setState(committed);
185
+ },
186
+ async apply () {
187
+ inFlight += 1;
188
+ setIsApplying(true);
189
+ const current = committed;
190
+ const reconnect = ()=>{
191
+ write(current);
192
+ return onApply?.({
193
+ urls: resolveFrom(current),
194
+ appPublicId: current.appPublicId,
195
+ overrides: {
196
+ ...current.overrides
197
+ }
198
+ }) ?? void 0;
199
+ };
200
+ const run = 1 === inFlight ? (async ()=>reconnect())() : queue.then(reconnect).then(()=>void 0);
201
+ queue = run.catch(()=>void 0);
202
+ try {
203
+ await run;
204
+ } finally{
205
+ inFlight -= 1;
206
+ if (0 === inFlight) setIsApplying(false);
207
+ }
208
+ }
209
+ };
210
+ };
211
+ export { createConnectionSettings, isAbsoluteUrl, isIpv6Literal };
@@ -0,0 +1,2 @@
1
+ export type { ConnectionEndpoint, ConnectionSettingsApplied, ConnectionSettingsOptions, ConnectionSettingsState, ConnectionSettingsStore, } from "./createConnectionSettings";
2
+ export { createConnectionSettings, isAbsoluteUrl } from "./createConnectionSettings";
@@ -0,0 +1 @@
1
+ export { createConnectionSettings, isAbsoluteUrl } from "./createConnectionSettings.js";
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Month and weekday names, and the four date strings the calendar assembles
3
+ * from them, without `Intl`.
4
+ *
5
+ * `Intl` is not defined in the chuzz browser. That is deliberate policy and
6
+ * the decision has been made not to ship ICU data, so `new Intl.DateTimeFormat`
7
+ * is not a formatter that returns a bad date, it is a `ReferenceError`. The
8
+ * throw escapes every boundary the component has and reaches Solid 2, which
9
+ * responds by halting its reactive system permanently: the page keeps painting
10
+ * the frame it already had, so it looks alive, while every control on it is
11
+ * dead. js.software's `/calendar` route is dead this way today, and nothing on
12
+ * the page says so.
13
+ *
14
+ * What the calendar actually needed from `Intl` was twelve month names, seven
15
+ * weekday names in three widths, and four assembly patterns. That is a table,
16
+ * so this is the table.
17
+ *
18
+ * ## The locale question
19
+ *
20
+ * Only `en-US` is carried here. A library that shipped name tables for every
21
+ * locale would be shipping ICU data by another name, which is the thing that
22
+ * was ruled out.
23
+ *
24
+ * The sites are not all English, so the names are an input: pass `dateNames`
25
+ * and the calendar renders yours. A site that already ships five locales
26
+ * through its own i18n has these strings; it hands over the set for the
27
+ * language it is currently in.
28
+ *
29
+ * When a consumer passes `locale="de-DE"` and no `dateNames`, the calendar
30
+ * renders English. It cannot do anything else, and the two dishonest options
31
+ * were to throw or to keep claiming German while showing "June". So it renders
32
+ * English *and says so*: `resolveDateNames` returns the locale actually
33
+ * rendered, and `Calendar` puts that on the root as `lang`. A page asking for
34
+ * German gets `lang="en-US"`, which is true, which an assistive technology
35
+ * reads correctly, and which a check can catch.
36
+ */
37
+ /** Weekday name width, matching the widths `Intl` calls `weekday`. */
38
+ export type DateNameWidth = "narrow" | "short" | "long";
39
+ /**
40
+ * The names a calendar needs to render.
41
+ *
42
+ * Every array is indexed positionally: months by `Date#getMonth` (0 is
43
+ * January), weekdays by `Date#getDay` (0 is Sunday). All five are required.
44
+ * A partial set was the friendlier API and the wrong one: German months beside
45
+ * English weekdays under `lang="de-DE"` is exactly the half-truth this module
46
+ * exists to avoid.
47
+ */
48
+ export type DateNames = {
49
+ /** 12 entries, `getMonth`-indexed. "January". */
50
+ monthsLong: readonly string[];
51
+ /** 12 entries, `getMonth`-indexed. "Jan". */
52
+ monthsShort: readonly string[];
53
+ /** 7 entries, `getDay`-indexed from Sunday. "S". */
54
+ weekdaysNarrow: readonly string[];
55
+ /** 7 entries, `getDay`-indexed from Sunday. "Sun". */
56
+ weekdaysShort: readonly string[];
57
+ /** 7 entries, `getDay`-indexed from Sunday. "Sunday". */
58
+ weekdaysLong: readonly string[];
59
+ };
60
+ /** The locale the built-in table transcribes. */
61
+ export declare const DEFAULT_DATE_LOCALE = "en-US";
62
+ /**
63
+ * `en-US`, transcribed from `Intl` rather than typed from memory.
64
+ *
65
+ * `tests/hooks/date/date-names.test.ts` regenerates every entry from a real
66
+ * `Intl.DateTimeFormat` under bun's ICU and compares, so a typo here is a test
67
+ * failure and not a wrong month in production.
68
+ */
69
+ export declare const EN_US_DATE_NAMES: DateNames;
70
+ /**
71
+ * Pick the names to render with, and report the locale that will actually be
72
+ * on screen.
73
+ *
74
+ * The returned `locale` is the honest one, not the requested one: it is the
75
+ * consumer's locale only when the consumer supplied the names to back it.
76
+ */
77
+ export declare const resolveDateNames: (locale: string | undefined, names: DateNames | undefined) => {
78
+ names: DateNames;
79
+ locale: string;
80
+ };
81
+ /**
82
+ * The grid heading. `{ month: "long", year: "numeric" }` in `en-US`.
83
+ *
84
+ * "June 2025".
85
+ */
86
+ export declare const formatMonthYear: (date: Date, names?: DateNames) => string;
87
+ /**
88
+ * A day button's `aria-label`. `{ dateStyle: "full" }` in `en-US`.
89
+ *
90
+ * "Sunday, June 15, 2025": long weekday, comma, long month, space, the day
91
+ * with no leading zero, comma, year.
92
+ */
93
+ export declare const formatFullDate: (date: Date, names?: DateNames) => string;
94
+ /**
95
+ * A picker's trigger text. `{ day: "numeric", month: "short", year: "numeric" }`
96
+ * in `en-US`.
97
+ *
98
+ * "Jun 15, 2025". Note that `Intl` orders this month-first for `en-US`
99
+ * regardless of the order the options are written in.
100
+ */
101
+ export declare const formatCompactDate: (date: Date, names?: DateNames) => string;
102
+ /**
103
+ * The seven column headers, Sunday first. `{ weekday: width }` in `en-US`.
104
+ *
105
+ * `["Sun", "Mon", ...]` at the default `short` width.
106
+ */
107
+ export declare const weekdayNames: (width: DateNameWidth, names?: DateNames) => readonly string[];
@@ -0,0 +1,74 @@
1
+ const DEFAULT_DATE_LOCALE = "en-US";
2
+ const EN_US_DATE_NAMES = {
3
+ monthsLong: [
4
+ "January",
5
+ "February",
6
+ "March",
7
+ "April",
8
+ "May",
9
+ "June",
10
+ "July",
11
+ "August",
12
+ "September",
13
+ "October",
14
+ "November",
15
+ "December"
16
+ ],
17
+ monthsShort: [
18
+ "Jan",
19
+ "Feb",
20
+ "Mar",
21
+ "Apr",
22
+ "May",
23
+ "Jun",
24
+ "Jul",
25
+ "Aug",
26
+ "Sep",
27
+ "Oct",
28
+ "Nov",
29
+ "Dec"
30
+ ],
31
+ weekdaysNarrow: [
32
+ "S",
33
+ "M",
34
+ "T",
35
+ "W",
36
+ "T",
37
+ "F",
38
+ "S"
39
+ ],
40
+ weekdaysShort: [
41
+ "Sun",
42
+ "Mon",
43
+ "Tue",
44
+ "Wed",
45
+ "Thu",
46
+ "Fri",
47
+ "Sat"
48
+ ],
49
+ weekdaysLong: [
50
+ "Sunday",
51
+ "Monday",
52
+ "Tuesday",
53
+ "Wednesday",
54
+ "Thursday",
55
+ "Friday",
56
+ "Saturday"
57
+ ]
58
+ };
59
+ const resolveDateNames = (locale, names)=>names ? {
60
+ names,
61
+ locale: locale ?? DEFAULT_DATE_LOCALE
62
+ } : {
63
+ names: EN_US_DATE_NAMES,
64
+ locale: DEFAULT_DATE_LOCALE
65
+ };
66
+ const formatMonthYear = (date, names = EN_US_DATE_NAMES)=>`${names.monthsLong[date.getMonth()] ?? ""} ${date.getFullYear()}`;
67
+ const formatFullDate = (date, names = EN_US_DATE_NAMES)=>`${names.weekdaysLong[date.getDay()] ?? ""}, ${names.monthsLong[date.getMonth()] ?? ""} ${date.getDate()}, ${date.getFullYear()}`;
68
+ const formatCompactDate = (date, names = EN_US_DATE_NAMES)=>`${names.monthsShort[date.getMonth()] ?? ""} ${date.getDate()}, ${date.getFullYear()}`;
69
+ const weekdayNames = (width, names = EN_US_DATE_NAMES)=>{
70
+ if ("narrow" === width) return names.weekdaysNarrow;
71
+ if ("long" === width) return names.weekdaysLong;
72
+ return names.weekdaysShort;
73
+ };
74
+ export { DEFAULT_DATE_LOCALE, EN_US_DATE_NAMES, formatCompactDate, formatFullDate, formatMonthYear, resolveDateNames, weekdayNames };
@@ -1,3 +1,4 @@
1
+ import { type DateNames } from "./date.names";
1
2
  export declare const DAYS_PER_WEEK = 7;
2
3
  export declare const CALENDAR_GRID_DAYS = 42;
3
4
  export type DateRangeValue = {
@@ -8,7 +9,16 @@ export declare const createCalendarDate: (year: number, monthIndex: number, day:
8
9
  export declare const normalizeDate: (value: Date | null | undefined) => Date | null;
9
10
  export declare const getToday: () => Date;
10
11
  export declare const parseDate: (value: string | null | undefined) => Date | null;
11
- export declare const formatDate: (value: Date | null | undefined, locale?: string, options?: Intl.DateTimeFormatOptions) => string;
12
+ /**
13
+ * The date a picker shows on its trigger. "Jun 15, 2025".
14
+ *
15
+ * The second parameter used to be a locale string and the third an
16
+ * `Intl.DateTimeFormatOptions`. Both are gone rather than kept as ignored
17
+ * arguments: a `locale` this function cannot honour is worse than no `locale`
18
+ * at all, and the component that owns the locale prop resolves it through
19
+ * `resolveDateNames` before calling here. See `date.names.ts`.
20
+ */
21
+ export declare const formatDate: (value: Date | null | undefined, names?: DateNames) => string;
12
22
  export declare const toISODate: (value: Date | null | undefined) => string;
13
23
  export declare const compareDates: (left: Date, right: Date) => number;
14
24
  export declare const compareMonths: (left: Date, right: Date) => number;
@@ -1,3 +1,4 @@
1
+ import { EN_US_DATE_NAMES, formatCompactDate } from "./date.names.js";
1
2
  const DAYS_PER_WEEK = 7;
2
3
  const CALENDAR_GRID_DAYS = 42;
3
4
  const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
@@ -23,14 +24,10 @@ const parseDate = (value)=>{
23
24
  if (parsed.getFullYear() !== year || parsed.getMonth() !== month - 1 || parsed.getDate() !== day) return null;
24
25
  return parsed;
25
26
  };
26
- const formatDate = (value, locale = "en-US", options = {
27
- day: "numeric",
28
- month: "short",
29
- year: "numeric"
30
- })=>{
27
+ const formatDate = (value, names = EN_US_DATE_NAMES)=>{
31
28
  const date = normalizeDate(value);
32
29
  if (!date) return "";
33
- return new Intl.DateTimeFormat(locale, options).format(date);
30
+ return formatCompactDate(date, names);
34
31
  };
35
32
  const pad = (value)=>String(value).padStart(2, "0");
36
33
  const toISODate = (value)=>{
@@ -1,3 +1,4 @@
1
+ export * from "./date.names";
1
2
  export * from "./date.utils";
2
3
  export * from "./useCalendarNavigation";
3
4
  export * from "./useCalendarState";
@@ -1,3 +1,4 @@
1
+ export * from "./date.names.js";
1
2
  export * from "./date.utils.js";
2
3
  export * from "./useCalendarNavigation.js";
3
4
  export * from "./useCalendarState.js";
@@ -1,9 +1,16 @@
1
1
  import { type Accessor } from "solid-js";
2
+ import { type DateNameWidth, type DateNames } from "./date.names";
2
3
  export type CalendarSelectionMode = "single" | "range";
3
4
  type CalendarStateOptions = {
4
5
  selectionMode: Accessor<CalendarSelectionMode>;
5
- locale: Accessor<string>;
6
- weekdayFormat: Accessor<"narrow" | "short" | "long">;
6
+ /**
7
+ * The names to render with. The owning component resolves these from its
8
+ * `locale` and `dateNames` props through `resolveDateNames`, so there is no
9
+ * `locale` here: this hook formats from a table and has nothing to do with
10
+ * one. See `date.names.ts`.
11
+ */
12
+ dateNames: Accessor<DateNames>;
13
+ weekdayFormat: Accessor<DateNameWidth>;
7
14
  visibleMonth: Accessor<Date>;
8
15
  focusedDate: Accessor<Date>;
9
16
  selectedDate: Accessor<Date | null>;
@@ -28,9 +35,9 @@ export type CalendarCellState = {
28
35
  isAriaSelected: boolean;
29
36
  };
30
37
  export declare const useCalendarState: (options: CalendarStateOptions) => {
31
- monthFormatter: import("solid-js").SourceAccessor<Intl.DateTimeFormat>;
32
- dayLabelFormatter: import("solid-js").SourceAccessor<Intl.DateTimeFormat>;
33
- weekdayLabels: import("solid-js").SourceAccessor<string[]>;
38
+ monthLabel: import("solid-js").SourceAccessor<string>;
39
+ formatDayLabel: (date: Date) => string;
40
+ weekdayLabels: import("solid-js").SourceAccessor<readonly string[]>;
34
41
  calendarWeeks: import("solid-js").SourceAccessor<Date[][]>;
35
42
  normalizedRange: import("solid-js").SourceAccessor<{
36
43
  start: Date | null;
@@ -1,22 +1,10 @@
1
1
  import { createMemo } from "solid-js";
2
- import { addDays, buildCalendarGrid, compareDates, createPreviewRange, getToday, isSameDay, isSameMonth, normalizeRange, splitWeeks } from "./date.utils.js";
2
+ import { formatFullDate, formatMonthYear, weekdayNames } from "./date.names.js";
3
+ import { buildCalendarGrid, compareDates, createPreviewRange, getToday, isSameDay, isSameMonth, normalizeRange, splitWeeks } from "./date.utils.js";
3
4
  const useCalendarState = (options)=>{
4
- const monthFormatter = createMemo(()=>new Intl.DateTimeFormat(options.locale(), {
5
- month: "long",
6
- year: "numeric"
7
- }));
8
- const dayLabelFormatter = createMemo(()=>new Intl.DateTimeFormat(options.locale(), {
9
- dateStyle: "full"
10
- }));
11
- const weekdayFormatter = createMemo(()=>new Intl.DateTimeFormat(options.locale(), {
12
- weekday: options.weekdayFormat()
13
- }));
14
- const weekdayLabels = createMemo(()=>{
15
- const firstSunday = new Date(2024, 0, 7, 12, 0, 0, 0);
16
- return Array.from({
17
- length: 7
18
- }, (_, index)=>weekdayFormatter().format(addDays(firstSunday, index)));
19
- });
5
+ const monthLabel = createMemo(()=>formatMonthYear(options.visibleMonth(), options.dateNames()));
6
+ const formatDayLabel = (date)=>formatFullDate(date, options.dateNames());
7
+ const weekdayLabels = createMemo(()=>weekdayNames(options.weekdayFormat(), options.dateNames()));
20
8
  const calendarWeeks = createMemo(()=>splitWeeks(buildCalendarGrid(options.visibleMonth(), 0)));
21
9
  const normalizedRange = createMemo(()=>normalizeRange(options.rangeStart(), options.rangeEnd()));
22
10
  const previewRange = createMemo(()=>createPreviewRange(normalizedRange().start, normalizedRange().end, options.rangePreview()));
@@ -54,8 +42,8 @@ const useCalendarState = (options)=>{
54
42
  };
55
43
  };
56
44
  return {
57
- monthFormatter,
58
- dayLabelFormatter,
45
+ monthLabel,
46
+ formatDayLabel,
59
47
  weekdayLabels,
60
48
  calendarWeeks,
61
49
  normalizedRange,
@@ -4,7 +4,7 @@ type AnyValues = Record<string, any>;
4
4
  export type AsyncValidatorFn<TValues extends AnyValues> = (context: {
5
5
  value: TValues;
6
6
  }) => Promise<Partial<Record<keyof TValues, string>> | undefined>;
7
- export type CreateFormOptions<TValues extends AnyValues = AnyValues> = {
7
+ export type CreateFormOptions<TValues extends AnyValues = AnyValues, TOutput = TValues> = {
8
8
  /**
9
9
  * Initial values for every field. Used to infer the form's value type and
10
10
  * to determine whether a field is "dirty".
@@ -14,7 +14,7 @@ export type CreateFormOptions<TValues extends AnyValues = AnyValues> = {
14
14
  * Any Standard Schema-compatible schema (Zod, Valibot, Arktype, ...).
15
15
  * Runs on change, on blur and on submit.
16
16
  */
17
- schema?: StandardSchemaV1<TValues>;
17
+ schema?: StandardSchemaV1<TValues, TOutput>;
18
18
  /**
19
19
  * Additional async validators for fields that need server-side validation
20
20
  * (e.g. username availability). These run *after* the synchronous schema.
@@ -26,7 +26,7 @@ export type CreateFormOptions<TValues extends AnyValues = AnyValues> = {
26
26
  /**
27
27
  * Called when the form is submitted and all validators pass.
28
28
  */
29
- onSubmit?: (value: TValues) => void | Promise<void>;
29
+ onSubmit?: (value: TOutput) => void | Promise<void>;
30
30
  };
31
31
  /** What a field tracks besides its value. */
32
32
  type FieldMeta = {
@@ -77,5 +77,5 @@ export type FormApi<TValues extends AnyValues = AnyValues> = {
77
77
  * field is touched — the display gate lives in `useField`, so a submit can
78
78
  * surface every error at once by touching every field.
79
79
  */
80
- export declare const createForm: <TValues extends AnyValues = AnyValues>(options: CreateFormOptions<TValues>) => FormApi<TValues>;
80
+ export declare const createForm: <TValues extends AnyValues = AnyValues, TOutput = TValues>(options: CreateFormOptions<TValues, TOutput>) => FormApi<TValues>;
81
81
  export { getFirstFieldError };
@@ -67,17 +67,15 @@ const createForm = (options)=>{
67
67
  };
68
68
  });
69
69
  flush();
70
- let ok = runSchema();
70
+ let output = values;
71
71
  const schema = options.schema;
72
72
  if (schema) {
73
- const result = schema["~standard"].validate(values);
74
- if (result instanceof Promise) {
75
- const resolved = await result;
76
- applyErrors(resolved.issues ? issuesToErrors(resolved.issues) : {}, true);
77
- ok = !resolved.issues?.length;
78
- }
73
+ const pending = schema["~standard"].validate(values);
74
+ const result = pending instanceof Promise ? await pending : pending;
75
+ applyErrors(result.issues ? issuesToErrors(result.issues) : {}, true);
76
+ if (result.issues) return;
77
+ output = result.value;
79
78
  }
80
- if (!ok) return;
81
79
  setStatus((draft)=>{
82
80
  draft.isSubmitting = true;
83
81
  });
@@ -96,7 +94,7 @@ const createForm = (options)=>{
96
94
  };
97
95
  });
98
96
  }
99
- await options.onSubmit?.(values);
97
+ await options.onSubmit?.(output);
100
98
  } finally{
101
99
  setStatus((draft)=>{
102
100
  draft.isSubmitting = false;
package/dist/index.d.ts CHANGED
@@ -19,8 +19,8 @@ export { Breadcrumb, BreadcrumbItem, } from "./components/breadcrumb";
19
19
  export type { ButtonProps } from "./components/button";
20
20
  export { default as Button } from "./components/button";
21
21
  export { PanelToggle, type PanelToggleProps, type PanelToggleSide, } from "./components/panel-toggle";
22
- export { type CalendarDayHoverHandler, type CalendarDaySelectHandler, type CalendarProps, type CalendarSelectionMode, type CalendarWeekdayFormat, default as Calendar, } from "./components/calendar";
23
- export type { CardElevation, CardMaterial, CardProps, CardSectionProps, } from "./components/card";
22
+ export { type CalendarDayHoverHandler, type CalendarDaySelectHandler, type CalendarProps, type CalendarSelectionMode, type CalendarWeekdayFormat, type DateNames, default as Calendar, } from "./components/calendar";
23
+ export type { CardElevation, CardMaterial, CardState, CardProps, CardSectionProps, } from "./components/card";
24
24
  export { Card as CardRoot, CardBody, CardFooter, CardHeader, default as Card, } from "./components/card";
25
25
  export { default as ChatBubble } from "./components/chatbubble";
26
26
  export { default as Checkbox } from "./components/checkbox";
@@ -51,7 +51,7 @@ export { createFlexGrid, default as FlexGrid } from "./components/flex-grid";
51
51
  export type { FooterProps, FooterTitleProps } from "./components/footer";
52
52
  export { default as Footer } from "./components/footer";
53
53
  export type { FieldErrorMessageProps, FormFieldProps, FormProps, FormRootProps, FormSubmitButtonProps, FormWithContextProps, } from "./components/form";
54
- export { default as Form, FormField, FormSubmitButton, FormWithContext, } from "./components/form";
54
+ export { FieldErrorMessage, default as Form, FormField, FormSubmitButton, FormWithContext, } from "./components/form";
55
55
  export { GlowCard, type GlowCardProps } from "./components/glow-card";
56
56
  export { default as Grid } from "./components/grid";
57
57
  export type { HeaderProps, HeaderRootProps } from "./components/header";
@@ -107,7 +107,7 @@ export type { ExpandToggleProps as TableExpandToggleProps, InlineConfirmProps as
107
107
  export { default as Table, ExpandToggle as TableExpandToggle, InlineConfirm as TableInlineConfirm, MobileListView as TableMobileListView, SortIcon as TableSortIcon, VirtualSpacerRow as TableVirtualSpacerRow, } from "./components/table";
108
108
  export type { TabIndicatorProps, TabListContainerProps, TabListProps, TabPanelProps, TabProps, TabSeparatorProps, TabsRootProps, } from "./components/tabs";
109
109
  export { default as Tabs } from "./components/tabs";
110
- export type { TextFamily, TextLeading, TextProps, TextRootProps, TextSize, TextTracking, TextTransform, TextVariant, TextWeight, } from "./components/text";
110
+ export type { TextAs, TextFamily, TextLeading, TextProps, TextRootProps, TextSize, TextTracking, TextTransform, TextVariant, TextWeight, } from "./components/text";
111
111
  export { default as Text } from "./components/text";
112
112
  export type { TextareaProps, TextareaRootProps, TextareaVariant, } from "./components/textarea";
113
113
  export { default as Textarea } from "./components/textarea";
@@ -123,6 +123,10 @@ export type { AnyFormApi, CreateFormOptions, FormApi, UseFieldResult, } from "./
123
123
  export { createForm, FormContext, getFirstFieldError, useField, useFormContext, } from "./hooks/form";
124
124
  export type { CreateMutationOptions, CreateQueryOptions, MutationResult, QueryResult, } from "./hooks/data";
125
125
  export { createMutation, createQuery, invalidateQueries, } from "./hooks/data";
126
+ export type { ConnectionEndpoint, ConnectionSettingsApplied, ConnectionSettingsOptions, ConnectionSettingsState, ConnectionSettingsStore, } from "./hooks/connection";
127
+ export { createConnectionSettings, isAbsoluteUrl } from "./hooks/connection";
128
+ export type { ConnectionSettingsEndpointLabel, ConnectionSettingsLabels, ConnectionSettingsProps, } from "./components/connection-settings";
129
+ export { ConnectionSettings } from "./components/connection-settings";
126
130
  export { useDesktop } from "./hooks/layout";
127
131
  export type { UseAnchoredOverlayPositionOptions } from "./hooks/table";
128
132
  export { useAnchoredOverlayPosition } from "./hooks/table";
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ export { FieldGroup, FieldsetActions, FieldsetLegend, default as Fieldset } from
32
32
  export { default as Flex } from "./components/flex/index.js";
33
33
  export { createFlexGrid, default as FlexGrid } from "./components/flex-grid/index.js";
34
34
  export { default as Footer } from "./components/footer/index.js";
35
- export { FormField, FormSubmitButton, FormWithContext, default as Form } from "./components/form/index.js";
35
+ export { FieldErrorMessage, FormField, FormSubmitButton, FormWithContext, default as Form } from "./components/form/index.js";
36
36
  export { GlowCard } from "./components/glow-card/index.js";
37
37
  export { default as Grid } from "./components/grid/index.js";
38
38
  export { default as Header } from "./components/header/index.js";
@@ -73,6 +73,8 @@ export { TooltipArrow, TooltipContent, TooltipTrigger, default as Tooltip } from
73
73
  export { FLAVORS, SIZES, SPACES, STATES, VARIANTS, isInvalid, resolveState } from "./components/vocabulary.js";
74
74
  export { FormContext, createForm, getFirstFieldError, useField, useFormContext } from "./hooks/form/index.js";
75
75
  export { createMutation, createQuery, invalidateQueries } from "./hooks/data/index.js";
76
+ export { createConnectionSettings, isAbsoluteUrl } from "./hooks/connection/index.js";
77
+ export { ConnectionSettings } from "./components/connection-settings/index.js";
76
78
  export { useDesktop } from "./hooks/layout/index.js";
77
79
  export { useAnchoredOverlayPosition } from "./hooks/table/index.js";
78
80
  export { evaluatePasswordRules, matchPasswordConfirmation } from "./passwordRules.js";