@svelte-thing/primitives 0.0.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 +1 -0
- package/dist/button/index.d.mts +9 -0
- package/dist/button/index.mjs +6 -0
- package/dist/chunk-D7D4PA-g.mjs +13 -0
- package/dist/context-BJAwVB1S.mjs +5 -0
- package/dist/context-D77KIx26.mjs +5 -0
- package/dist/context-DwEoOJU2.mjs +5 -0
- package/dist/createInput.svelte-DTz79zNF.d.mts +9 -0
- package/dist/createInput.svelte-DzcT9u1t.mjs +92 -0
- package/dist/field/date/index.d.mts +2 -0
- package/dist/field/date/index.mjs +27 -0
- package/dist/field/error/index.d.mts +2 -0
- package/dist/field/error/index.mjs +10 -0
- package/dist/field/index.d.mts +13 -0
- package/dist/field/index.mjs +25 -0
- package/dist/field/input/index.d.mts +2 -0
- package/dist/field/input/index.mjs +2 -0
- package/dist/field/label/index.d.mts +2 -0
- package/dist/field/label/index.mjs +15 -0
- package/dist/field/password/index.d.mts +2 -0
- package/dist/field/password/index.mjs +61 -0
- package/dist/field/root/index.d.mts +2 -0
- package/dist/field/root/index.mjs +79 -0
- package/dist/index-07sbgO0w.d.mts +9 -0
- package/dist/index-B-PBb_8h.d.mts +14 -0
- package/dist/index-BLb5EVhG.d.mts +35 -0
- package/dist/index-BVVgDSdq.d.mts +1 -0
- package/dist/index-Boej-mdy.d.mts +25 -0
- package/dist/index-C-ME1Tk9.d.mts +9 -0
- package/dist/index-CA_POIj_.d.mts +9 -0
- package/dist/index-CbchmhrC.d.mts +9 -0
- package/dist/index-D2vzMU8o.d.mts +13 -0
- package/dist/index-DAHEDQQS.d.mts +9 -0
- package/dist/index-OI9KlY5x.d.mts +9 -0
- package/dist/index-j-8eH9nJ.d.mts +29 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +3 -0
- package/dist/menu/index.d.mts +5 -0
- package/dist/menu/index.mjs +6 -0
- package/dist/menu/item/index.d.mts +14 -0
- package/dist/menu/item/index.mjs +86 -0
- package/dist/menu/popup/index.d.mts +19 -0
- package/dist/menu/popup/index.mjs +121 -0
- package/dist/menu/root/index.d.mts +28 -0
- package/dist/menu/root/index.mjs +69 -0
- package/dist/menu/trigger/index.d.mts +13 -0
- package/dist/menu/trigger/index.mjs +27 -0
- package/dist/pagination/content/index.d.mts +9 -0
- package/dist/pagination/content/index.mjs +6 -0
- package/dist/pagination/ellipsis/index.d.mts +9 -0
- package/dist/pagination/ellipsis/index.mjs +6 -0
- package/dist/pagination/index.d.mts +6 -0
- package/dist/pagination/index.mjs +6 -0
- package/dist/pagination/item/index.d.mts +9 -0
- package/dist/pagination/item/index.mjs +6 -0
- package/dist/pagination/link/index.d.mts +13 -0
- package/dist/pagination/link/index.mjs +13 -0
- package/dist/pagination/root/index.d.mts +9 -0
- package/dist/pagination/root/index.mjs +9 -0
- package/dist/tab/index.d.mts +13 -0
- package/dist/tab/index.mjs +21 -0
- package/dist/tab/indicator/index.d.mts +2 -0
- package/dist/tab/indicator/index.mjs +42 -0
- package/dist/tab/list/index.d.mts +2 -0
- package/dist/tab/list/index.mjs +20 -0
- package/dist/tab/panel/index.d.mts +2 -0
- package/dist/tab/panel/index.mjs +28 -0
- package/dist/tab/root/index.d.mts +2 -0
- package/dist/tab/root/index.mjs +57 -0
- package/dist/tab/title/index.d.mts +2 -0
- package/dist/tab/title/index.mjs +18 -0
- package/dist/tab/trigger/index.d.mts +2 -0
- package/dist/tab/trigger/index.mjs +94 -0
- package/dist/table/index.d.mts +2 -0
- package/dist/table/index.mjs +2 -0
- package/dist/table/row/index.d.mts +17 -0
- package/dist/table/row/index.mjs +17 -0
- package/package.json +64 -0
- package/src/button/createButton.svelte.ts +11 -0
- package/src/button/index.ts +1 -0
- package/src/field/date/createPicker.svelte.ts +41 -0
- package/src/field/date/index.ts +1 -0
- package/src/field/error/createError.svelte.ts +21 -0
- package/src/field/error/index.ts +1 -0
- package/src/field/index.ts +6 -0
- package/src/field/input/createInput.svelte.ts +136 -0
- package/src/field/input/index.ts +1 -0
- package/src/field/label/createLabel.svelte.ts +24 -0
- package/src/field/label/index.ts +1 -0
- package/src/field/password/context.ts +5 -0
- package/src/field/password/createPassword.svelte.ts +43 -0
- package/src/field/password/createShow.svelte.ts +47 -0
- package/src/field/password/index.ts +3 -0
- package/src/field/root/context.ts +5 -0
- package/src/field/root/createRoot.svelte.ts +113 -0
- package/src/field/root/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/menu/index.ts +4 -0
- package/src/menu/item/createItem.svelte.ts +123 -0
- package/src/menu/item/index.ts +1 -0
- package/src/menu/popup/createPopup.svelte.ts +186 -0
- package/src/menu/popup/index.ts +1 -0
- package/src/menu/root/context.ts +5 -0
- package/src/menu/root/createRoot.svelte.ts +96 -0
- package/src/menu/root/index.ts +2 -0
- package/src/menu/trigger/createTrigger.svelte.ts +44 -0
- package/src/menu/trigger/index.ts +1 -0
- package/src/pagination/content/createContent.svelte.ts +11 -0
- package/src/pagination/content/index.ts +1 -0
- package/src/pagination/ellipsis/createEllipsis.svelte.ts +13 -0
- package/src/pagination/ellipsis/index.ts +1 -0
- package/src/pagination/index.ts +5 -0
- package/src/pagination/item/createItem.svelte.ts +11 -0
- package/src/pagination/item/index.ts +1 -0
- package/src/pagination/link/createLink.svelte.ts +23 -0
- package/src/pagination/link/index.ts +1 -0
- package/src/pagination/root/createRoot.svelte.ts +14 -0
- package/src/pagination/root/index.ts +1 -0
- package/src/style.css +10 -0
- package/src/tab/index.ts +6 -0
- package/src/tab/indicator/createIndicator.svelte.ts +79 -0
- package/src/tab/indicator/index.ts +1 -0
- package/src/tab/list/createList.svelte.ts +27 -0
- package/src/tab/list/index.ts +1 -0
- package/src/tab/panel/createPanel.svelte.ts +42 -0
- package/src/tab/panel/index.ts +1 -0
- package/src/tab/root/context.ts +5 -0
- package/src/tab/root/createRoot.svelte.ts +85 -0
- package/src/tab/root/index.ts +2 -0
- package/src/tab/title/createTitle.svelte.ts +27 -0
- package/src/tab/title/index.ts +1 -0
- package/src/tab/trigger/createTrigger.svelte.ts +129 -0
- package/src/tab/trigger/index.ts +1 -0
- package/src/table/index.ts +1 -0
- package/src/table/row/context.ts +5 -0
- package/src/table/row/createRow.svelte.ts +26 -0
- package/src/table/row/index.ts +2 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { n as setRoot, t as getRoot } from "../../context-DwEoOJU2.mjs";
|
|
2
|
+
import { uid } from "uid";
|
|
3
|
+
//#region src/tab/root/createRoot.svelte.ts
|
|
4
|
+
function createRoot(props) {
|
|
5
|
+
const activateOnFocus = $derived(props.activateOnFocus ?? true);
|
|
6
|
+
const direction = $derived(props.direction ?? "ltr");
|
|
7
|
+
const id = $derived(uid());
|
|
8
|
+
const orientation = $derived(props.orientation ?? "horizontal");
|
|
9
|
+
let hasTitle = $state(false);
|
|
10
|
+
let value = $derived(props.value ?? null);
|
|
11
|
+
let panel = $derived(props.value ?? null);
|
|
12
|
+
const root = {
|
|
13
|
+
get activateOnFocus() {
|
|
14
|
+
return activateOnFocus;
|
|
15
|
+
},
|
|
16
|
+
get direction() {
|
|
17
|
+
return direction;
|
|
18
|
+
},
|
|
19
|
+
get hasTitle() {
|
|
20
|
+
return hasTitle;
|
|
21
|
+
},
|
|
22
|
+
set hasTitle(h) {
|
|
23
|
+
hasTitle = h;
|
|
24
|
+
},
|
|
25
|
+
get id() {
|
|
26
|
+
return id;
|
|
27
|
+
},
|
|
28
|
+
get orientation() {
|
|
29
|
+
return orientation;
|
|
30
|
+
},
|
|
31
|
+
get panel() {
|
|
32
|
+
return panel;
|
|
33
|
+
},
|
|
34
|
+
set panel(p) {
|
|
35
|
+
panel = p;
|
|
36
|
+
},
|
|
37
|
+
get value() {
|
|
38
|
+
return value;
|
|
39
|
+
},
|
|
40
|
+
set value(v) {
|
|
41
|
+
value = v;
|
|
42
|
+
},
|
|
43
|
+
props: {
|
|
44
|
+
get "data-orientation"() {
|
|
45
|
+
return orientation;
|
|
46
|
+
},
|
|
47
|
+
get id() {
|
|
48
|
+
return id;
|
|
49
|
+
},
|
|
50
|
+
"data-tab-root": ""
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
setRoot(root);
|
|
54
|
+
return root;
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { createRoot, getRoot, setRoot };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { t as getRoot } from "../../context-DwEoOJU2.mjs";
|
|
2
|
+
import { onDestroy } from "svelte";
|
|
3
|
+
//#region src/tab/title/createTitle.svelte.ts
|
|
4
|
+
function createTitle() {
|
|
5
|
+
const root = getRoot();
|
|
6
|
+
root.hasTitle = true;
|
|
7
|
+
onDestroy(() => {
|
|
8
|
+
root.hasTitle = false;
|
|
9
|
+
});
|
|
10
|
+
return { props: {
|
|
11
|
+
get id() {
|
|
12
|
+
return `${root.id}-title`;
|
|
13
|
+
},
|
|
14
|
+
"data-tab-title": ""
|
|
15
|
+
} };
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { createTitle };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { t as getRoot } from "../../context-DwEoOJU2.mjs";
|
|
2
|
+
//#region src/tab/trigger/createTrigger.svelte.ts
|
|
3
|
+
function createTrigger(props) {
|
|
4
|
+
const root = getRoot();
|
|
5
|
+
const isSelected = $derived(root.value === props.value);
|
|
6
|
+
if (root.value === null) {
|
|
7
|
+
root.value = props.value;
|
|
8
|
+
root.panel = props.value;
|
|
9
|
+
}
|
|
10
|
+
return { props: {
|
|
11
|
+
get "aria-controls"() {
|
|
12
|
+
return `${root.id}-panel-${props.value}`;
|
|
13
|
+
},
|
|
14
|
+
get "aria-selected"() {
|
|
15
|
+
return isSelected;
|
|
16
|
+
},
|
|
17
|
+
get "data-disabled"() {
|
|
18
|
+
return props.disabled ? true : void 0;
|
|
19
|
+
},
|
|
20
|
+
get "data-orientation"() {
|
|
21
|
+
return root.orientation;
|
|
22
|
+
},
|
|
23
|
+
get "data-root-id"() {
|
|
24
|
+
return root.id;
|
|
25
|
+
},
|
|
26
|
+
get "data-selected"() {
|
|
27
|
+
return isSelected ? "" : void 0;
|
|
28
|
+
},
|
|
29
|
+
get "data-value"() {
|
|
30
|
+
return props.value;
|
|
31
|
+
},
|
|
32
|
+
get id() {
|
|
33
|
+
return `${root.id}-trigger-${props.value}`;
|
|
34
|
+
},
|
|
35
|
+
get tabindex() {
|
|
36
|
+
return isSelected ? void 0 : -1;
|
|
37
|
+
},
|
|
38
|
+
"data-tabs-trigger": "",
|
|
39
|
+
type: "button",
|
|
40
|
+
role: "tab",
|
|
41
|
+
onclick(event) {
|
|
42
|
+
root.value = props.value;
|
|
43
|
+
root.panel = props.value;
|
|
44
|
+
event.currentTarget.focus();
|
|
45
|
+
},
|
|
46
|
+
onkeydown(event) {
|
|
47
|
+
if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return;
|
|
48
|
+
let preventDefault = false;
|
|
49
|
+
let pendingValue = null;
|
|
50
|
+
const button = event.currentTarget;
|
|
51
|
+
const triggers = [...document.querySelectorAll(`[data-tabs-trigger][data-root-id="${root.id}"]:not([data-disabled])`)];
|
|
52
|
+
const currentIndex = triggers.indexOf(button);
|
|
53
|
+
const nextKeyName = root.orientation === "horizontal" ? "ArrowRight" : "ArrowDown";
|
|
54
|
+
const previousKeyName = root.orientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
|
|
55
|
+
switch (event.key) {
|
|
56
|
+
case previousKeyName: {
|
|
57
|
+
const nextIndex = currentIndex === 0 ? triggers.length - 1 : currentIndex - 1;
|
|
58
|
+
pendingValue = triggers[nextIndex]?.dataset.value ?? null;
|
|
59
|
+
triggers[nextIndex]?.focus();
|
|
60
|
+
preventDefault = true;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case nextKeyName: {
|
|
64
|
+
const nextIndex = (currentIndex + 1) % triggers.length;
|
|
65
|
+
pendingValue = triggers[nextIndex]?.dataset.value ?? null;
|
|
66
|
+
triggers[nextIndex]?.focus();
|
|
67
|
+
preventDefault = true;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case "Home":
|
|
71
|
+
pendingValue = triggers[0]?.dataset.value ?? null;
|
|
72
|
+
triggers[0]?.focus();
|
|
73
|
+
preventDefault = true;
|
|
74
|
+
break;
|
|
75
|
+
case "End":
|
|
76
|
+
pendingValue = triggers.at(-1)?.dataset.value ?? null;
|
|
77
|
+
triggers.at(-1)?.focus();
|
|
78
|
+
preventDefault = true;
|
|
79
|
+
break;
|
|
80
|
+
default: break;
|
|
81
|
+
}
|
|
82
|
+
if (pendingValue !== null) {
|
|
83
|
+
root.value = pendingValue;
|
|
84
|
+
if (root.activateOnFocus) root.panel = pendingValue;
|
|
85
|
+
}
|
|
86
|
+
if (preventDefault) {
|
|
87
|
+
event.stopPropagation();
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} };
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { createTrigger };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Exact } from "@svelte-thing/type-utils";
|
|
2
|
+
import { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
|
|
4
|
+
//#region src/table/row/createRow.svelte.d.ts
|
|
5
|
+
interface CreateRowProps {
|
|
6
|
+
href: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
interface RowState {
|
|
9
|
+
href: string | undefined;
|
|
10
|
+
props: HTMLAttributes<HTMLElement>;
|
|
11
|
+
}
|
|
12
|
+
declare function createRow<T extends CreateRowProps>(props: Exact<CreateRowProps, T>): RowState;
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/table/row/context.d.ts
|
|
15
|
+
declare const getRow: () => RowState, setRow: (context: RowState) => RowState;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { CreateRowProps, RowState, createRow, getRow, setRow };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createContext } from "svelte";
|
|
2
|
+
//#region src/table/row/context.ts
|
|
3
|
+
const [getRow, setRow] = createContext();
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/table/row/createRow.svelte.ts
|
|
6
|
+
function createRow(props) {
|
|
7
|
+
const row = {
|
|
8
|
+
get href() {
|
|
9
|
+
return props.href;
|
|
10
|
+
},
|
|
11
|
+
props: {}
|
|
12
|
+
};
|
|
13
|
+
setRow(row);
|
|
14
|
+
return row;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { createRow, getRow, setRow };
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@svelte-thing/primitives",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"files": [
|
|
5
|
+
"src",
|
|
6
|
+
"dist",
|
|
7
|
+
"!**/*.test.js",
|
|
8
|
+
"!**/*.test.js.map",
|
|
9
|
+
"!**/*.test.d.ts"
|
|
10
|
+
],
|
|
11
|
+
"type": "module",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./dist/index.mjs",
|
|
14
|
+
"./button": "./dist/button/index.mjs",
|
|
15
|
+
"./field": "./dist/field/index.mjs",
|
|
16
|
+
"./field/date": "./dist/field/date/index.mjs",
|
|
17
|
+
"./field/error": "./dist/field/error/index.mjs",
|
|
18
|
+
"./field/input": "./dist/field/input/index.mjs",
|
|
19
|
+
"./field/label": "./dist/field/label/index.mjs",
|
|
20
|
+
"./field/password": "./dist/field/password/index.mjs",
|
|
21
|
+
"./field/root": "./dist/field/root/index.mjs",
|
|
22
|
+
"./menu": "./dist/menu/index.mjs",
|
|
23
|
+
"./menu/item": "./dist/menu/item/index.mjs",
|
|
24
|
+
"./menu/popup": "./dist/menu/popup/index.mjs",
|
|
25
|
+
"./menu/root": "./dist/menu/root/index.mjs",
|
|
26
|
+
"./menu/trigger": "./dist/menu/trigger/index.mjs",
|
|
27
|
+
"./pagination": "./dist/pagination/index.mjs",
|
|
28
|
+
"./pagination/content": "./dist/pagination/content/index.mjs",
|
|
29
|
+
"./pagination/ellipsis": "./dist/pagination/ellipsis/index.mjs",
|
|
30
|
+
"./pagination/item": "./dist/pagination/item/index.mjs",
|
|
31
|
+
"./pagination/link": "./dist/pagination/link/index.mjs",
|
|
32
|
+
"./pagination/root": "./dist/pagination/root/index.mjs",
|
|
33
|
+
"./tab": "./dist/tab/index.mjs",
|
|
34
|
+
"./tab/indicator": "./dist/tab/indicator/index.mjs",
|
|
35
|
+
"./tab/list": "./dist/tab/list/index.mjs",
|
|
36
|
+
"./tab/panel": "./dist/tab/panel/index.mjs",
|
|
37
|
+
"./tab/root": "./dist/tab/root/index.mjs",
|
|
38
|
+
"./tab/title": "./dist/tab/title/index.mjs",
|
|
39
|
+
"./tab/trigger": "./dist/tab/trigger/index.mjs",
|
|
40
|
+
"./table": "./dist/table/index.mjs",
|
|
41
|
+
"./table/row": "./dist/table/row/index.mjs",
|
|
42
|
+
"./package.json": "./package.json"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@svelte-thing/component-utils": "^0.0.16",
|
|
46
|
+
"@svelte-thing/type-utils": "^0.0.1",
|
|
47
|
+
"esm-env": "^1.2.2",
|
|
48
|
+
"uid": "2.0.2"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@arethetypeswrong/core": "^0.18.3",
|
|
52
|
+
"@svelte-thing/tailwind-radix-colors": "^0.0.0",
|
|
53
|
+
"@sveltejs/package": "^2.5.8",
|
|
54
|
+
"publint": "0.3.21",
|
|
55
|
+
"svelte": "5.53.7",
|
|
56
|
+
"tailwindcss": "4.1.18",
|
|
57
|
+
"typescript": "6.0.3",
|
|
58
|
+
"vite-plus": "^0.1.24"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"svelte": "5.53.7",
|
|
62
|
+
"tailwindcss": "4.1.18"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createButton.svelte.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
2
|
+
|
|
3
|
+
import { getRoot } from '../root/context.js';
|
|
4
|
+
|
|
5
|
+
export interface PickerState {
|
|
6
|
+
props: HTMLButtonAttributes;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function createPicker(): PickerState {
|
|
10
|
+
const root = getRoot();
|
|
11
|
+
const picker: PickerState = {
|
|
12
|
+
props: {
|
|
13
|
+
get disabled() {
|
|
14
|
+
return root.isDisabled;
|
|
15
|
+
},
|
|
16
|
+
get 'aria-controls'() {
|
|
17
|
+
return root.controlId;
|
|
18
|
+
},
|
|
19
|
+
get 'data-disabled'() {
|
|
20
|
+
return root.isDisabled ? '' : undefined;
|
|
21
|
+
},
|
|
22
|
+
type: 'button',
|
|
23
|
+
onmousedown(event) {
|
|
24
|
+
// Prevent losing focus on the input when clicking the toggle.
|
|
25
|
+
event.preventDefault();
|
|
26
|
+
},
|
|
27
|
+
onclick() {
|
|
28
|
+
if (root.isDisabled) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const input = document.getElementById(root.controlId) as HTMLInputElement | null;
|
|
33
|
+
if (input && 'showPicker' in input) {
|
|
34
|
+
input.showPicker();
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return picker;
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createPicker.svelte.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
|
|
3
|
+
import { getRoot } from '../root/context.js';
|
|
4
|
+
|
|
5
|
+
export interface ErrorState {
|
|
6
|
+
props: HTMLAttributes<HTMLElement>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function createError(): ErrorState {
|
|
10
|
+
const root = getRoot();
|
|
11
|
+
|
|
12
|
+
const error: ErrorState = {
|
|
13
|
+
props: {
|
|
14
|
+
get id() {
|
|
15
|
+
return root.errorId;
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return error;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createError.svelte.js';
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
|
|
3
|
+
import { getRoot } from '../root/context.js';
|
|
4
|
+
import type { RootState } from '../root/createRoot.svelte.js';
|
|
5
|
+
|
|
6
|
+
export interface InputState {
|
|
7
|
+
props: HTMLInputAttributes;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type Control = HTMLInputElement;
|
|
11
|
+
|
|
12
|
+
function isCheckboxOrRadio(
|
|
13
|
+
control: Control,
|
|
14
|
+
): control is HTMLInputElement & { type: 'checkbox' | 'radio' } {
|
|
15
|
+
return control.type === 'checkbox' || control.type === 'radio';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isFilled(control: Control) {
|
|
19
|
+
if (isCheckboxOrRadio(control)) {
|
|
20
|
+
return control.checked;
|
|
21
|
+
}
|
|
22
|
+
return control.value !== '';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function syncValidity(root: RootState, control: Control) {
|
|
26
|
+
// If the control doesn't participate in constraint validation, don't force
|
|
27
|
+
// validity state changes.
|
|
28
|
+
if (!control.willValidate) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const { valid } = control.validity;
|
|
33
|
+
root.isValid = valid;
|
|
34
|
+
root.isInvalid = !valid;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function createInput(): InputState {
|
|
38
|
+
const root = getRoot();
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
props: {
|
|
42
|
+
get id() {
|
|
43
|
+
return root.controlId;
|
|
44
|
+
},
|
|
45
|
+
get disabled() {
|
|
46
|
+
return root.isDisabled;
|
|
47
|
+
},
|
|
48
|
+
get 'aria-invalid'() {
|
|
49
|
+
return root.isInvalid ? true : undefined;
|
|
50
|
+
},
|
|
51
|
+
get 'aria-describedby'() {
|
|
52
|
+
return root.isInvalid ? root.errorId : undefined;
|
|
53
|
+
},
|
|
54
|
+
get 'data-disabled'() {
|
|
55
|
+
return root.isDisabled ? '' : undefined;
|
|
56
|
+
},
|
|
57
|
+
get 'data-valid'() {
|
|
58
|
+
return root.isValid ? '' : undefined;
|
|
59
|
+
},
|
|
60
|
+
get 'data-invalid'() {
|
|
61
|
+
return root.isInvalid ? '' : undefined;
|
|
62
|
+
},
|
|
63
|
+
get 'data-dirty'() {
|
|
64
|
+
return root.isDirty ? '' : undefined;
|
|
65
|
+
},
|
|
66
|
+
get 'data-touched'() {
|
|
67
|
+
return root.isTouched ? '' : undefined;
|
|
68
|
+
},
|
|
69
|
+
get 'data-filled'() {
|
|
70
|
+
return root.isFilled ? '' : undefined;
|
|
71
|
+
},
|
|
72
|
+
get 'data-focused'() {
|
|
73
|
+
return root.isFocused ? '' : undefined;
|
|
74
|
+
},
|
|
75
|
+
onchange(event) {
|
|
76
|
+
if (root.isDisabled) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const input = event.currentTarget;
|
|
81
|
+
|
|
82
|
+
root.isDirty = true;
|
|
83
|
+
root.isFilled = isFilled(input);
|
|
84
|
+
syncValidity(root, input);
|
|
85
|
+
},
|
|
86
|
+
oninput(event) {
|
|
87
|
+
if (root.isDisabled) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const input = event.currentTarget;
|
|
92
|
+
|
|
93
|
+
root.isDirty = true;
|
|
94
|
+
root.isFilled = isFilled(input);
|
|
95
|
+
syncValidity(root, input);
|
|
96
|
+
},
|
|
97
|
+
onfocus(event) {
|
|
98
|
+
if (root.isDisabled) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const input = event.currentTarget;
|
|
103
|
+
|
|
104
|
+
root.isFocused = true;
|
|
105
|
+
root.isFilled = isFilled(input);
|
|
106
|
+
syncValidity(root, input);
|
|
107
|
+
},
|
|
108
|
+
onblur(event) {
|
|
109
|
+
if (root.isDisabled) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const input = event.currentTarget;
|
|
114
|
+
|
|
115
|
+
root.isFocused = false;
|
|
116
|
+
root.isTouched = true;
|
|
117
|
+
root.isFilled = isFilled(input);
|
|
118
|
+
syncValidity(root, input);
|
|
119
|
+
},
|
|
120
|
+
onkeydown(event) {
|
|
121
|
+
if (root.isDisabled) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (event.key !== 'Enter') {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const input = event.currentTarget;
|
|
129
|
+
|
|
130
|
+
root.isTouched = true;
|
|
131
|
+
root.isFilled = isFilled(input);
|
|
132
|
+
syncValidity(root, input);
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createInput.svelte.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { HTMLLabelAttributes } from 'svelte/elements';
|
|
2
|
+
|
|
3
|
+
import { getRoot } from '../root/context.js';
|
|
4
|
+
|
|
5
|
+
export interface LabelState {
|
|
6
|
+
props: HTMLLabelAttributes;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function createLabel(): LabelState {
|
|
10
|
+
const root = getRoot();
|
|
11
|
+
|
|
12
|
+
const label: LabelState = {
|
|
13
|
+
props: {
|
|
14
|
+
get for() {
|
|
15
|
+
return root.controlId;
|
|
16
|
+
},
|
|
17
|
+
get id() {
|
|
18
|
+
return root.labelId;
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return label;
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createLabel.svelte.js';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { mergeProps } from '@svelte-thing/component-utils';
|
|
2
|
+
import type { Exact } from '@svelte-thing/type-utils';
|
|
3
|
+
|
|
4
|
+
import { type InputState, createInput } from '../input/createInput.svelte.js';
|
|
5
|
+
import { setPassword } from './context.js';
|
|
6
|
+
|
|
7
|
+
export interface CreatePasswordProps {
|
|
8
|
+
isVisible: boolean | null | undefined;
|
|
9
|
+
type: 'password' | null | undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface PasswordState extends InputState {
|
|
13
|
+
isVisible: boolean;
|
|
14
|
+
toggle: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createPassword<T extends CreatePasswordProps>(
|
|
18
|
+
props: Exact<CreatePasswordProps, T>,
|
|
19
|
+
): PasswordState {
|
|
20
|
+
let isVisible = $derived(props.isVisible ?? false);
|
|
21
|
+
|
|
22
|
+
const input = createInput();
|
|
23
|
+
const password: PasswordState = mergeProps(input, {
|
|
24
|
+
get isVisible() {
|
|
25
|
+
return isVisible;
|
|
26
|
+
},
|
|
27
|
+
set isVisible(visible) {
|
|
28
|
+
isVisible = visible;
|
|
29
|
+
},
|
|
30
|
+
toggle() {
|
|
31
|
+
isVisible = !isVisible;
|
|
32
|
+
},
|
|
33
|
+
props: {
|
|
34
|
+
get type() {
|
|
35
|
+
return isVisible ? 'text' : 'password';
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
setPassword(password);
|
|
41
|
+
|
|
42
|
+
return password;
|
|
43
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
2
|
+
|
|
3
|
+
import { getRoot } from '../root/context.js';
|
|
4
|
+
import { getPassword } from './context.js';
|
|
5
|
+
|
|
6
|
+
export interface ShowState {
|
|
7
|
+
props: HTMLButtonAttributes;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function createShow(): ShowState {
|
|
11
|
+
const root = getRoot();
|
|
12
|
+
const password = getPassword();
|
|
13
|
+
const show: ShowState = {
|
|
14
|
+
props: {
|
|
15
|
+
get disabled() {
|
|
16
|
+
return root.isDisabled;
|
|
17
|
+
},
|
|
18
|
+
get 'aria-controls'() {
|
|
19
|
+
return root.controlId;
|
|
20
|
+
},
|
|
21
|
+
get 'aria-pressed'() {
|
|
22
|
+
return password.isVisible;
|
|
23
|
+
},
|
|
24
|
+
get 'data-disabled'() {
|
|
25
|
+
return root.isDisabled ? '' : undefined;
|
|
26
|
+
},
|
|
27
|
+
get 'data-visible'() {
|
|
28
|
+
return password.isVisible ? '' : undefined;
|
|
29
|
+
},
|
|
30
|
+
type: 'button',
|
|
31
|
+
onmousedown(event) {
|
|
32
|
+
// Prevent losing focus on the input when clicking the toggle.
|
|
33
|
+
event.preventDefault();
|
|
34
|
+
},
|
|
35
|
+
onclick() {
|
|
36
|
+
if (root.isDisabled) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
password.toggle();
|
|
41
|
+
document.getElementById(root.controlId)?.focus?.();
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return show;
|
|
47
|
+
}
|