@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.
- package/README.md +13 -2
- package/dist/components/accordion/Accordion.css +24 -1
- package/dist/components/alert/Alert.css +11 -1
- package/dist/components/auth-field-group/AuthFieldGroup.css +11 -3
- package/dist/components/button/Button.css +37 -10
- package/dist/components/calendar/Calendar.generated.d.ts +19 -2
- package/dist/components/calendar/Calendar.generated.js +30 -23
- package/dist/components/calendar/index.d.ts +1 -1
- package/dist/components/card/Card.generated.d.ts +38 -2
- package/dist/components/card/Card.generated.js +99 -45
- package/dist/components/card/Card.interactions.d.ts +70 -0
- package/dist/components/card/Card.interactions.js +19 -0
- package/dist/components/card/index.d.ts +1 -1
- package/dist/components/checkbox/Checkbox.generated.d.ts +23 -2
- package/dist/components/checkbox/Checkbox.generated.js +14 -6
- package/dist/components/collapsible/Collapsible.css +17 -1
- package/dist/components/color-wheel-flower/ColorWheelFlower.generated.d.ts +8 -0
- package/dist/components/color-wheel-flower/ColorWheelFlower.generated.js +14 -1
- package/dist/components/color-wheel-flower/colorWheelFlowerContext.d.ts +9 -2
- package/dist/components/color-wheel-flower/colorWheelFlowerContext.js +2 -4
- package/dist/components/connection-settings/ConnectionSettings.css +76 -0
- package/dist/components/connection-settings/ConnectionSettings.generated.d.ts +45 -0
- package/dist/components/connection-settings/ConnectionSettings.generated.js +300 -0
- package/dist/components/connection-settings/ConnectionSettings.recipe.d.ts +54 -0
- package/dist/components/connection-settings/ConnectionSettings.recipe.js +111 -0
- package/dist/components/connection-settings/index.d.ts +2 -0
- package/dist/components/connection-settings/index.js +1 -0
- package/dist/components/date-picker/DatePicker.generated.d.ts +3 -1
- package/dist/components/date-picker/DatePicker.generated.js +8 -5
- package/dist/components/date-range-picker/DateRangePicker.generated.d.ts +3 -1
- package/dist/components/date-range-picker/DateRangePicker.generated.js +9 -6
- package/dist/components/dialog/Dialog.generated.js +17 -79
- package/dist/components/drawer/Drawer.a11y.d.ts +1 -3
- package/dist/components/drawer/Drawer.a11y.js +2 -30
- package/dist/components/drawer/Drawer.generated.d.ts +24 -0
- package/dist/components/drawer/Drawer.generated.js +65 -58
- package/dist/components/grid/Grid.generated.js +3 -3
- package/dist/components/icon/Icon.generated.d.ts +15 -0
- package/dist/components/icon/Icon.generated.js +11 -2
- package/dist/components/immersive-landing/ImmersiveLanding.css +1 -1
- package/dist/components/immersive-landing/components/CookieConsent.interactions.d.ts +24 -0
- package/dist/components/immersive-landing/components/CookieConsent.interactions.js +2 -0
- package/dist/components/immersive-landing/components/CookieConsent.js +52 -47
- package/dist/components/immersive-landing/components/FirefoxPWABanner.js +10 -10
- package/dist/components/immersive-landing/types.d.ts +15 -0
- package/dist/components/input/Input.css +5 -3
- package/dist/components/input/Input.generated.js +6 -3
- package/dist/components/language-switcher/LanguageSwitcher.generated.js +1 -1
- package/dist/components/live-chat/LiveChatPanel.generated.js +2 -6
- package/dist/components/live-chat/LiveChatPanel.interactions.d.ts +21 -0
- package/dist/components/live-chat/LiveChatPanel.interactions.js +10 -0
- package/dist/components/password-field/PasswordField.generated.d.ts +9 -1
- package/dist/components/password-field/PasswordField.generated.js +2 -2
- package/dist/components/password-field/PasswordField.interactions.d.ts +2 -2
- package/dist/components/password-field/PasswordField.interactions.js +2 -2
- package/dist/components/popover/Popover.a11y.d.ts +47 -0
- package/dist/components/popover/Popover.a11y.js +19 -0
- package/dist/components/popover/Popover.generated.d.ts +26 -0
- package/dist/components/popover/Popover.generated.js +119 -46
- package/dist/components/radio/Radio.generated.d.ts +26 -2
- package/dist/components/radio/Radio.generated.js +9 -5
- package/dist/components/range-calendar/RangeCalendar.generated.d.ts +3 -1
- package/dist/components/range-calendar/RangeCalendar.generated.js +4 -1
- package/dist/components/select/Select.generated.js +5 -0
- package/dist/components/slider/Slider.generated.d.ts +14 -1
- package/dist/components/slider/Slider.generated.js +3 -2
- package/dist/components/switch/Switch.css +0 -3
- package/dist/components/switch/Switch.generated.d.ts +23 -2
- package/dist/components/switch/Switch.generated.js +21 -44
- package/dist/components/switch/Switch.recipe.d.ts +61 -38
- package/dist/components/switch/Switch.recipe.js +88 -68
- package/dist/components/table/MobileListView.generated.js +1 -1
- package/dist/components/text/Text.generated.d.ts +26 -1
- package/dist/components/text/Text.generated.js +14 -13
- package/dist/components/text/Text.recipe.d.ts +17 -5
- package/dist/components/text/Text.recipe.js +7 -13
- package/dist/components/text/index.d.ts +1 -1
- package/dist/components/theme-color-picker/ThemeColorPicker.generated.js +1 -1
- package/dist/hooks/connection/createConnectionSettings.d.ts +128 -0
- package/dist/hooks/connection/createConnectionSettings.js +211 -0
- package/dist/hooks/connection/index.d.ts +2 -0
- package/dist/hooks/connection/index.js +1 -0
- package/dist/hooks/date/date.names.d.ts +107 -0
- package/dist/hooks/date/date.names.js +74 -0
- package/dist/hooks/date/date.utils.d.ts +11 -1
- package/dist/hooks/date/date.utils.js +3 -6
- package/dist/hooks/date/index.d.ts +1 -0
- package/dist/hooks/date/index.js +1 -0
- package/dist/hooks/date/useCalendarState.d.ts +12 -5
- package/dist/hooks/date/useCalendarState.js +7 -19
- package/dist/hooks/form/createForm.d.ts +4 -4
- package/dist/hooks/form/createForm.js +7 -9
- package/dist/index.d.ts +8 -4
- package/dist/index.js +3 -1
- package/dist/layouts.manifest.json +4 -1
- package/dist/lib/focus.d.ts +31 -0
- package/dist/lib/focus.js +39 -0
- package/dist/lib/overlay.d.ts +94 -0
- package/dist/lib/overlay.js +72 -0
- package/dist/purge-manifest.json +14427 -15269
- package/dist/responsive-classes.txt +450 -0
- package/dist/styles/base/index.css +42 -0
- 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 @@
|
|
|
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
|
-
|
|
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,
|
|
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
|
|
30
|
+
return formatCompactDate(date, names);
|
|
34
31
|
};
|
|
35
32
|
const pad = (value)=>String(value).padStart(2, "0");
|
|
36
33
|
const toISODate = (value)=>{
|
package/dist/hooks/date/index.js
CHANGED
|
@@ -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
|
-
|
|
6
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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 {
|
|
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
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
58
|
-
|
|
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:
|
|
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
|
|
70
|
+
let output = values;
|
|
71
71
|
const schema = options.schema;
|
|
72
72
|
if (schema) {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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?.(
|
|
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";
|