signal-layers 0.0.6 → 0.1.1

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/src/Spinner.jsx CHANGED
@@ -1,155 +1,57 @@
1
1
  export function Spinner(contract = {}) {
2
- /* ────────────────────────────────────────────────────────────────────────────
3
- * CONTRACT
4
- * ────────────────────────────────────────────────────────────────────────────
5
- *
6
- * Spinner - Animated loading indicator with customizable appearance
7
- *
8
- * Foundation: CSS animated div with spinning border
9
- *
10
- * Signals:
11
- * Size: xs, sm, md, lg, xl
12
- * Color: light, primary, danger
13
- * Border: thin, thick
14
- * Animation: spinSlow, spinFast, pause
15
- * Layout: inline, block, centered
16
- * Visibility: transparent
17
- *
18
- * Data:
19
- * ariaLabel - Accessibility label for screen readers
20
- *
21
- * Defaults: md, inline, spin
22
- *
23
- * Usage:
24
- * <Spinner />
25
- * <Spinner lg primary />
26
- * <Spinner sm light transparent />
27
- *
28
- * ──────────────────────────────────────────────────────────────────────────── */
2
+ const { layer, data, state, classes, signals } = createSignalUtils(contract);
3
+ const { inputSignal, layerSignal, dataSignal } = signals;
4
+ let spinner;
29
5
 
30
- const [inputSignal, layerSignal, dataSignal] = [{ ...contract }, {}, {}];
6
+ spinner = {
7
+ layout: layer("layout", "spinner"),
8
+ size: layer("size", "spinner"),
9
+ color: layer("color", "spinner"),
10
+ border: layer("border", "spinner"),
11
+ animation: layer("animation", "spinner"),
12
+ visibility: layer("visibility", "spinner"),
13
+ };
31
14
 
32
- /* ────────────────────────────────────────────────────────────────────────────
33
- * CONTRACT TOOLS
34
- * ──────────────────────────────────────────────────────────────────────────── */
15
+ spinner.layout("inline-flex items-center justify-center");
16
+ spinner.color("border-black/20 border-t-black");
17
+ spinner.border("border-2 rounded-full");
18
+ spinner.animation("animate-spin");
19
+ spinner.visibility("opacity-100");
20
+ spinner.size("w-6 h-6");
35
21
 
36
- const layer = (name) => (className) =>
37
- (layerSignal[name] ||= [],
38
- (layerSignal[name][0] = className));
22
+ inputSignal.xs && spinner.size("w-3 h-3 border");
23
+ inputSignal.sm && spinner.size("w-4 h-4 border-2");
24
+ inputSignal.md && spinner.size("w-6 h-6 border-2");
25
+ inputSignal.lg && spinner.size("w-8 h-8 border-4");
26
+ inputSignal.xl && spinner.size("w-12 h-12 border-4");
39
27
 
40
- const data = (name, key = name) =>
41
- inputSignal[key] && (dataSignal[name] = inputSignal[key]);
28
+ inputSignal.light && spinner.color("border-white/30 border-t-white");
29
+ inputSignal.primary && spinner.color("border-blue-600/30 border-t-blue-500");
30
+ inputSignal.danger && spinner.color("border-red-600/30 border-t-red-500");
42
31
 
43
- const classes = (layers = {}) =>
44
- Object.values(layers).map(l => l[0]).filter(Boolean).join(" ");
32
+ inputSignal.thin && spinner.border("border rounded-full");
33
+ inputSignal.thick && spinner.border("border-4 rounded-full");
34
+
35
+ inputSignal.spinSlow &&
36
+ spinner.animation("animate-spin [animation-duration:1.5s]");
37
+ inputSignal.spinFast &&
38
+ spinner.animation("animate-spin [animation-duration:.6s]");
39
+ inputSignal.pause &&
40
+ spinner.animation("animate-spin [animation-play-state:paused]");
41
+
42
+ inputSignal.inline && spinner.layout("inline-flex");
43
+ inputSignal.block && spinner.layout("block mx-auto");
44
+ inputSignal.centered && spinner.layout("flex mx-auto");
45
+
46
+ inputSignal.transparent && spinner.visibility("opacity-25");
47
+
48
+ inputSignal.ariaLabel && data("ariaLabel");
45
49
 
46
- /* ────────────────────────────────────────────────────────────────────────────
47
- * BASE LAYERS
48
- * ──────────────────────────────────────────────────────────────────────────── */
49
- let spinner;
50
- (() =>
51
- (
52
- spinner = {
53
- layout:layer("layout"),
54
- size:layer("size"),
55
- color:layer("color"),
56
- border:layer("border"),
57
- animation:layer("animation"),
58
- visibility:layer("visibility")
59
- }
60
- )
61
- )(),
62
- /* ────────────────────────────────────────────────────────────────────────────
63
- * DEFAULTS
64
- * ──────────────────────────────────────────────────────────────────────────── */
65
- (() =>
66
- (
67
- spinner.layout("inline-flex items-center justify-center"),
68
- spinner.color("border-black/20 border-t-black"),
69
- spinner.border("border-2 rounded-full"),
70
- spinner.animation("animate-spin"),
71
- spinner.visibility("opacity-100"),
72
- spinner.size("w-6 h-6")
73
- )
74
- )(),
75
- /* ────────────────────────────────────────────────────────────────────────────
76
- * SIZE SIGNALS
77
- * ──────────────────────────────────────────────────────────────────────────── */
78
- (() =>
79
- (
80
- inputSignal.xs && spinner.size("w-3 h-3 border"),
81
- inputSignal.sm && spinner.size("w-4 h-4 border-2"),
82
- inputSignal.md && spinner.size("w-6 h-6 border-2"),
83
- inputSignal.lg && spinner.size("w-8 h-8 border-4"),
84
- inputSignal.xl && spinner.size("w-12 h-12 border-4")
85
- )
86
- )(),
87
- /* ────────────────────────────────────────────────────────────────────────────
88
- * COLOR SIGNALS
89
- * ──────────────────────────────────────────────────────────────────────────── */
90
- (() =>
91
- (
92
-
93
- inputSignal.light && spinner.color("border-white/30 border-t-white"),
94
- inputSignal.primary && spinner.color("border-blue-600/30 border-t-blue-500"),
95
- inputSignal.danger && spinner.color("border-red-600/30 border-t-red-500")
96
- )
97
- )(),
98
- /* ────────────────────────────────────────────────────────────────────────────
99
- * BORDER SIGNALS
100
- * ──────────────────────────────────────────────────────────────────────────── */
101
- (() =>
102
- (
103
-
104
- inputSignal.thin && spinner.border("border rounded-full"),
105
- inputSignal.thick && spinner.border("border-4 rounded-full")
106
- )
107
- )(),
108
- /* ────────────────────────────────────────────────────────────────────────────
109
- * ANIMATION SIGNALS
110
- * ──────────────────────────────────────────────────────────────────────────── */
111
- (() =>
112
- (
113
-
114
- inputSignal.spinSlow && spinner.animation("animate-spin [animation-duration:1.5s]"),
115
- inputSignal.spinFast && spinner.animation("animate-spin [animation-duration:.6s]"),
116
- inputSignal.pause && spinner.animation("animate-spin [animation-play-state:paused]")
117
- )
118
- )(),
119
- /* ────────────────────────────────────────────────────────────────────────────
120
- * LAYOUT SIGNALS
121
- * ──────────────────────────────────────────────────────────────────────────── */
122
- (() =>
123
- (
124
- inputSignal.inline && spinner.layout("inline-flex"),
125
- inputSignal.block && spinner.layout("block mx-auto"),
126
- inputSignal.centered && spinner.layout("flex mx-auto")
127
- )
128
- )(),
129
- /* ────────────────────────────────────────────────────────────────────────────
130
- * VISIBILITY SIGNALS
131
- * ──────────────────────────────────────────────────────────────────────────── */
132
- (() =>
133
- (
134
- inputSignal.transparent && spinner.visibility("opacity-25")
135
- )
136
- )(),
137
- /* ────────────────────────────────────────────────────────────────────────────
138
- * DATA
139
- * ──────────────────────────────────────────────────────────────────────────── */
140
- (() =>
141
- (
142
- inputSignal.ariaLabel && data("ariaLabel")
143
- )
144
- )();
145
- /* ────────────────────────────────────────────────────────────────────────────
146
- * RENDER
147
- * ──────────────────────────────────────────────────────────────────────────── */
148
50
  return (
149
51
  <div
150
52
  role="status"
151
53
  aria-label={dataSignal.ariaLabel || "loading"}
152
- className={classes(layerSignal)}
54
+ className={classes(layerSignal.spinner)}
153
55
  />
154
56
  );
155
- }
57
+ }
package/src/Switch.jsx CHANGED
@@ -1,152 +1,124 @@
1
- import { useState } from "react";
2
-
3
- export function Switch(contract = {}) {
4
-
5
- const [inputSignal, layerSignal, dataSignal, stateSignal] = [{ ...contract }, {}, {}, {}];
6
- const switchId = `switch-${Math.random().toString(36).substring(2, 9)}`;
7
-
8
- const layer = (name, scope = "checkbox") => (className) =>
9
- (layerSignal[scope] ||= {},
10
- layerSignal[scope][name] ||= [],
11
- (layerSignal[scope][name][0] = className));
12
-
13
- const data = (name, key = name) =>
14
- inputSignal[key] !== undefined && (dataSignal[name] = inputSignal[key]);
15
-
16
- const state = (name, priority = 0, initial = false) => (
17
- (stateSignal._hooks ||= {})[name] ||= (() => {
18
- const [get, set] = useState(initial);
19
- return { get, set };
20
- })(),
21
- priority &&
22
- (!stateSignal._priority || priority > stateSignal._priority) &&
23
- (stateSignal[name] = stateSignal._hooks[name],
24
- stateSignal._priority = priority)
25
- );
26
-
27
- const classes = (layers = {}) =>
28
- Object.values(layers).map(l => l[0]).filter(Boolean).join(" ");
29
-
30
- let container;
31
- let button;
32
- let thumb;
33
- let label;
34
-
35
- container = {
36
- base: layer("base", "container"),
37
- size: layer("size", "container"),
38
- color: layer("color", "container"),
39
- layout: layer("layout", "container")
40
- }
1
+ export function Switch(contract = {}) {
2
+ const { layer, data, state, classes, signals } = createSignalUtils(contract);
3
+ const { inputSignal, layerSignal, dataSignal, stateSignal } = signals;
4
+ const switchId = `switch-${Math.random().toString(36).substring(2, 9)}`;
5
+
6
+ let container, button, thumb, label;
7
+
8
+ container = {
9
+ base: layer("base", "container"),
10
+ size: layer("size", "container"),
11
+ color: layer("color", "container"),
12
+ layout: layer("layout", "container")
13
+ }
41
14
 
42
- button = {
43
- base: layer("base", "button"),
44
- size: layer("size", "button"),
45
- color: layer("color", "button"),
46
- shape: layer("shape", "button"),
47
- layout: layer("layout", "button"),
48
- checked: layer("checked", "button"),
49
- interactive: layer("interactive", "button")
50
- }
15
+ button = {
16
+ base: layer("base", "button"),
17
+ size: layer("size", "button"),
18
+ color: layer("color", "button"),
19
+ shape: layer("shape", "button"),
20
+ layout: layer("layout", "button"),
21
+ checked: layer("checked", "button"),
22
+ interactive: layer("interactive", "button")
23
+ }
51
24
 
52
- thumb = {
53
- base: layer("base", "thumb"),
54
- color: layer("color", "thumb"),
55
- shape: layer("shape", "thumb"),
56
- size: layer("size", "thumb"),
57
- layout: layer("layout", "thumb"),
58
- position: layer("position", "thumb"),
59
- interactive: layer("interactive", "thumb")
60
- }
25
+ thumb = {
26
+ base: layer("base", "thumb"),
27
+ color: layer("color", "thumb"),
28
+ shape: layer("shape", "thumb"),
29
+ size: layer("size", "thumb"),
30
+ layout: layer("layout", "thumb"),
31
+ position: layer("position", "thumb"),
32
+ interactive: layer("interactive", "thumb")
33
+ }
61
34
 
62
- label = {
63
- base: layer("base", "label"),
64
- color: layer("color", "label"),
65
- layout: layer("layout", "label"),
66
- size: layer("size", "label")
67
- }
35
+ label = {
36
+ base: layer("base", "label"),
37
+ color: layer("color", "label"),
38
+ layout: layer("layout", "label"),
39
+ size: layer("size", "label")
40
+ }
68
41
 
69
- container.base("relative");
70
- container.size("h-4 w-8");
71
- container.color("bg-transparent");
72
- container.layout("inline-flex items-center gap-2");
73
-
74
- button.base("relative transition-colors duration-500 cursor-pointer");
75
- button.size("h-4 w-8");
76
- button.color("bg-gray-200");
77
- button.shape("rounded-full");
78
- button.layout("inline-flex items-center");
79
- button.checked("checked:bg-blue-600");
80
-
81
- thumb.base("absolute transition-transform duration-500");
82
- thumb.color("bg-white");
83
- thumb.shape("rounded-full");
84
- thumb.size("h-4 w-4");
85
- thumb.layout("inline-block");
86
- thumb.position("translate-x-0");
87
-
88
- label.base("absolute cursor-pointer whitespace-nowrap");
89
- label.color("text-gray-700");
90
- label.size("text-sm font-light");
91
- label.layout("left-12");
92
-
93
- inputSignal.xs && (
94
- container.size("h-3 w-6"),
95
- button.size("h-3 w-6"),
96
- thumb.size("h-3 w-3")
97
- )
98
- inputSignal.sm && (
99
- container.size("h-4 w-8"),
100
- button.size("h-4 w-8"),
101
- thumb.size("h-4 w-4")
102
- )
103
- inputSignal.md && (
104
- container.size("h-5 w-10"),
105
- button.size("h-5 w-10"),
106
- thumb.size("h-5 w-5")
107
- )
108
- inputSignal.lg && (
109
- container.size("h-6 w-12"),
110
- button.size("h-6 w-12"),
111
- thumb.size("h-6 w-6")
112
- )
113
-
114
- inputSignal.square && (button.shape("rounded-md"), thumb.shape("rounded-md"));
115
- inputSignal.pill && (button.shape("rounded-full"), thumb.shape("rounded-full"));
116
-
117
- inputSignal.labelLeft && label.layout("right-12 left-auto");
118
- inputSignal.labelRight && label.layout("left-12");
119
- inputSignal.labelTop && label.layout("bottom-8 left-0 right-0");
120
- inputSignal.labelBottom && label.layout("top-8 left-0 right-0");
121
- inputSignal.labelHidden && label.base("absolute opacity-0 pointer-events-none");
122
-
123
- inputSignal.disabled && (button.interactive("cursor-not-allowed opacity-40"), thumb.interactive("opacity-40"));
124
-
125
- inputSignal.id && data("id");
126
- inputSignal.label && data("label");
127
- inputSignal.name && data("name");
128
- inputSignal.value && data("value");
129
- inputSignal.checked && data("checked");
130
- inputSignal.defaultChecked && data("defaultChecked");
131
- inputSignal.disabled && data("disabled");
132
- inputSignal.required && data("required");
133
- inputSignal.readOnly && data("readOnly");
134
- inputSignal.ariaLabel && data("aria-label");
135
- inputSignal.ariaLabelledBy && data("aria-labelledby");
136
- inputSignal.ariaDescribedBy && data("aria-describedby");
137
- inputSignal.ariaInvalid && data("aria-invalid");
138
- inputSignal.ariaChecked && data("aria-checked");
139
-
140
-
141
- state("checked", 1, false);
142
- stateSignal.checked?.get && (
143
- thumb.position("translate-x-4"),
144
- inputSignal.xs && thumb.position("translate-x-3"),
145
- inputSignal.sm && thumb.position("translate-x-4"),
146
- inputSignal.md && thumb.position("translate-x-5"),
147
- inputSignal.lg && thumb.position("translate-x-6"),
148
- button.color("bg-blue-600")
149
- );
42
+ container.base("relative");
43
+ container.size("h-4 w-8");
44
+ container.color("bg-transparent");
45
+ container.layout("inline-flex items-center gap-2");
46
+
47
+ button.base("relative transition-colors duration-500 cursor-pointer");
48
+ button.size("h-4 w-8");
49
+ button.color("bg-gray-200");
50
+ button.shape("rounded-full");
51
+ button.layout("inline-flex items-center");
52
+ button.checked("checked:bg-blue-600");
53
+
54
+ thumb.base("absolute transition-transform duration-500");
55
+ thumb.color("bg-white");
56
+ thumb.shape("rounded-full");
57
+ thumb.size("h-4 w-4");
58
+ thumb.layout("inline-block");
59
+ thumb.position("translate-x-0");
60
+
61
+ label.base("absolute cursor-pointer whitespace-nowrap");
62
+ label.color("text-gray-700");
63
+ label.size("text-sm font-light");
64
+ label.layout("left-12");
65
+
66
+ inputSignal.xs && (
67
+ container.size("h-3 w-6"),
68
+ button.size("h-3 w-6"),
69
+ thumb.size("h-3 w-3")
70
+ )
71
+ inputSignal.sm && (
72
+ container.size("h-4 w-8"),
73
+ button.size("h-4 w-8"),
74
+ thumb.size("h-4 w-4")
75
+ )
76
+ inputSignal.md && (
77
+ container.size("h-5 w-10"),
78
+ button.size("h-5 w-10"),
79
+ thumb.size("h-5 w-5")
80
+ )
81
+ inputSignal.lg && (
82
+ container.size("h-6 w-12"),
83
+ button.size("h-6 w-12"),
84
+ thumb.size("h-6 w-6")
85
+ )
86
+
87
+ inputSignal.square && (button.shape("rounded-md"), thumb.shape("rounded-md"));
88
+ inputSignal.pill && (button.shape("rounded-full"), thumb.shape("rounded-full"));
89
+
90
+ inputSignal.labelLeft && label.layout("right-12 left-auto");
91
+ inputSignal.labelRight && label.layout("left-12");
92
+ inputSignal.labelTop && label.layout("bottom-8 left-0 right-0");
93
+ inputSignal.labelBottom && label.layout("top-8 left-0 right-0");
94
+ inputSignal.labelHidden && label.base("absolute opacity-0 pointer-events-none");
95
+
96
+ inputSignal.disabled && (button.interactive("cursor-not-allowed opacity-40"), thumb.interactive("opacity-40"));
97
+
98
+ inputSignal.id && data("id");
99
+ inputSignal.label && data("label");
100
+ inputSignal.name && data("name");
101
+ inputSignal.value && data("value");
102
+ inputSignal.checked && data("checked");
103
+ inputSignal.defaultChecked && data("defaultChecked");
104
+ inputSignal.disabled && data("disabled");
105
+ inputSignal.required && data("required");
106
+ inputSignal.readOnly && data("readOnly");
107
+ inputSignal.ariaLabel && data("aria-label");
108
+ inputSignal.ariaLabelledBy && data("aria-labelledby");
109
+ inputSignal.ariaDescribedBy && data("aria-describedby");
110
+ inputSignal.ariaInvalid && data("aria-invalid");
111
+ inputSignal.ariaChecked && data("aria-checked");
112
+
113
+ state("checked", 1, false);
114
+ stateSignal.checked?.get && (
115
+ thumb.position("translate-x-4"),
116
+ inputSignal.xs && thumb.position("translate-x-3"),
117
+ inputSignal.sm && thumb.position("translate-x-4"),
118
+ inputSignal.md && thumb.position("translate-x-5"),
119
+ inputSignal.lg && thumb.position("translate-x-6"),
120
+ button.color("bg-blue-600")
121
+ );
150
122
 
151
123
  return (
152
124
  <div className={classes(layerSignal.container)}>