@auldrant/ui 0.0.0 → 0.5.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.
@@ -1 +1 @@
1
- ._button_4gn7y_1{padding:.5em 1em;border:1px solid var(--aui-color-border);border-radius:.25em;background:var(--aui-color-primary);color:var(--aui-color-background);font:inherit;cursor:pointer}._button_4gn7y_1:hover{background:var(--aui-color-primary-hover)}._card_awzw5_1{display:grid;gap:.5em;padding:1em;border:1px solid var(--aui-color-border);border-radius:.25em;background:var(--aui-color-surface)}._field_sfa1d_1{display:grid;grid-template-columns:auto 1fr;align-items:center;gap:.5em}._form_rchcx_1{display:grid;gap:1em}._actions_rchcx_6{display:grid;grid-auto-flow:column;justify-content:start;gap:.5em}._field_18ejg_1{display:grid;grid-template-columns:auto 1fr;align-items:start;gap:.5em}._label_18ejg_8{padding-top:.25em}._required_18ejg_12{color:var(--aui-color-error)}._nav_778nl_1{display:grid;gap:.5em}._title_778nl_6{font-weight:700}._wrapper_1mu6v_1{display:grid;grid-template-columns:1fr auto}._input_1mu6v_6{border-top-right-radius:0;border-bottom-right-radius:0;border-right:none}._toggle_1mu6v_13{padding:.375em .75em;border:1px solid var(--aui-color-border);border-top-right-radius:.25em;border-bottom-right-radius:.25em;background:var(--aui-color-background);color:var(--aui-color-text);font:inherit;font-size:.875em;cursor:pointer}._toggle_1mu6v_13:hover:not(:disabled){background:var(--aui-color-background-hover, var(--aui-color-background))}._fieldset_19vke_1{border:none;padding:0}._legend_19vke_6{font-weight:700;margin-bottom:.5em}._option_19vke_11{display:grid;grid-template-columns:auto 1fr;align-items:center;gap:.5em;margin-bottom:.25em}._section_4nogy_1{display:grid;gap:1em}._skip_xbsul_1{position:absolute;top:-100%;left:0;padding:.5em 1em;background:var(--aui-color-background);color:var(--aui-color-primary);z-index:1000}._skip_xbsul_1:focus{top:0}._table_roeo7_1{width:100%;border-collapse:collapse}._table_roeo7_1 th,._table_roeo7_1 td{padding:.5em;text-align:left;border-bottom:1px solid var(--aui-color-border)}._table_roeo7_1 th{font-weight:700;color:var(--aui-color-text)}._table_roeo7_1 td{color:var(--aui-color-text)}._wrapper_1kyv1_1{display:grid;gap:.25em}._textarea_1kyv1_6{resize:vertical}._counter_1kyv1_11{justify-self:end;font-size:.875em;color:var(--aui-color-text-muted)}._theme_13mb7_1{display:contents}._focus-ring_4m0e1_3:focus-visible{outline:2px solid var(--aui-color-focus-ring);outline-offset:2px}._disabled_4m0e1_8:disabled{opacity:.5;cursor:not-allowed}._text-input_4m0e1_13{padding:.375em .5em;border:1px solid var(--aui-color-border);border-radius:.25em;background:var(--aui-color-background);color:var(--aui-color-text);font:inherit}._link_4m0e1_22{color:var(--aui-color-primary);text-decoration:underline;cursor:pointer}._link_4m0e1_22:hover{color:var(--aui-color-primary-hover)}._check-input_4m0e1_32{accent-color:var(--aui-color-primary)}._visually-hidden_4m0e1_36{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
1
+ ._button_4gn7y_1{padding:.5em 1em;border:1px solid var(--aui-color-border);border-radius:.25em;background:var(--aui-color-primary);color:var(--aui-color-background);font:inherit;cursor:pointer}._button_4gn7y_1:hover{background:var(--aui-color-primary-hover)}._card_awzw5_1{display:grid;gap:.5em;padding:1em;border:1px solid var(--aui-color-border);border-radius:.25em;background:var(--aui-color-surface)}._field_17xwz_1{display:grid;grid-template-columns:auto 1fr;align-items:center;gap:.5em}._error_17xwz_12{grid-column:2}._form_jr324_1{display:grid;gap:1em}._actions_jr324_6{display:grid;grid-auto-flow:column;justify-content:start;gap:.5em}._status_jr324_13{margin:0;font-size:.875em;color:var(--aui-color-text-muted)}._field_7l9ux_1{display:grid;grid-template-columns:auto 1fr;align-items:start;gap:.5em}._label_7l9ux_8{padding-top:.25em}._required_7l9ux_12{color:var(--aui-color-error)}._error_7l9ux_16{grid-column:2}._nav_778nl_1{display:grid;gap:.5em}._title_778nl_6{font-weight:700}._wrapper_1mu6v_1{display:grid;grid-template-columns:1fr auto}._input_1mu6v_6{border-top-right-radius:0;border-bottom-right-radius:0;border-right:none}._toggle_1mu6v_13{padding:.375em .75em;border:1px solid var(--aui-color-border);border-top-right-radius:.25em;border-bottom-right-radius:.25em;background:var(--aui-color-background);color:var(--aui-color-text);font:inherit;font-size:.875em;cursor:pointer}._toggle_1mu6v_13:hover:not(:disabled){background:var(--aui-color-background-hover, var(--aui-color-background))}._fieldset_lymkd_1{border:none;padding:0}._legend_lymkd_6{font-weight:700;margin-bottom:.5em}._option_lymkd_11{display:grid;grid-template-columns:auto 1fr;align-items:center;gap:.5em;margin-bottom:.25em}._section_4nogy_1{display:grid;gap:1em}._skip_xbsul_1{position:absolute;top:-100%;left:0;padding:.5em 1em;background:var(--aui-color-background);color:var(--aui-color-primary);z-index:1000}._skip_xbsul_1:focus{top:0}._table_dls60_1{width:100%;border-collapse:collapse}._caption_dls60_6{text-align:left;padding:.5em 0;font-weight:700}._table_dls60_1 th,._table_dls60_1 td{padding:.5em;text-align:left;border-bottom:1px solid var(--aui-color-border)}._table_dls60_1 th{font-weight:700;color:var(--aui-color-text)}._table_dls60_1 td{color:var(--aui-color-text)}._focus-ring_4u8pk_3:focus-visible{outline:2px solid var(--aui-color-focus-ring);outline-offset:2px}._disabled_4u8pk_8:disabled{opacity:.5;cursor:not-allowed}._text-input_4u8pk_13{padding:.375em .5em;border:1px solid var(--aui-color-border);border-radius:.25em;background:var(--aui-color-background);color:var(--aui-color-text);font:inherit}._link_4u8pk_22{color:var(--aui-color-primary);text-decoration:underline;cursor:pointer}._link_4u8pk_22:hover{color:var(--aui-color-primary-hover)}._check-input_4u8pk_32{accent-color:var(--aui-color-primary)}._field-error_4u8pk_36{margin:0;font-size:.875em;color:var(--aui-color-error)}._visually-hidden_4u8pk_42{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}._wrapper_1kyv1_1{display:grid;gap:.25em}._textarea_1kyv1_6{resize:vertical}._counter_1kyv1_11{justify-self:end;font-size:.875em;color:var(--aui-color-text-muted)}._theme_13mb7_1{display:contents}
@@ -1,424 +1,545 @@
1
- import { jsx as a, jsxs as _, Fragment as T } from "preact/jsx-runtime";
2
- import { useId as b } from "preact/hooks";
3
- import { signal as $, useSignal as j, effect as D } from "@preact/signals";
4
- function h(...t) {
1
+ import { jsx as r, jsxs as b, Fragment as W } from "preact/jsx-runtime";
2
+ import { useId as f } from "preact/hooks";
3
+ import { signal as j, useSignal as x, effect as M } from "@preact/signals";
4
+ function m(...t) {
5
5
  return t.filter(Boolean).join(" ");
6
6
  }
7
- const E = "_button_4gn7y_1 _focus-ring_4m0e1_3 _disabled_4m0e1_8", B = {
8
- button: E
9
- }, I = (t) => {
10
- const { label: e, onClick: l, type: n = "button", disabled: s, class: c } = t;
11
- return /* @__PURE__ */ a("button", { type: n, class: h(B.button, c), onClick: l, disabled: s, children: e });
12
- }, H = "_card_awzw5_1", O = {
13
- card: H
14
- }, Te = (t) => {
15
- const { children: e, class: l } = t;
16
- return /* @__PURE__ */ a("div", { class: h(O.card, l), children: e });
17
- }, R = "_field_sfa1d_1", G = "_input_sfa1d_8 _check-input_4m0e1_32 _focus-ring_4m0e1_3 _disabled_4m0e1_8", C = {
18
- field: R,
19
- input: G
20
- }, De = (t) => {
21
- const { label: e, name: l, checked: n, required: s, disabled: c, onChange: o, class: d } = t, u = b();
22
- return /* @__PURE__ */ _("div", { class: h(C.field, d), children: [
23
- /* @__PURE__ */ a(
7
+ function g(...t) {
8
+ return t.filter(Boolean).join(" ") || void 0;
9
+ }
10
+ const V = "_button_4gn7y_1 _focus-ring_4u8pk_3 _disabled_4u8pk_8", J = {
11
+ button: V
12
+ }, D = (t) => {
13
+ const { label: e, onClick: n, type: s = "button", disabled: l, class: c } = t;
14
+ return /* @__PURE__ */ r("button", { type: s, class: m(J.button, c), onClick: n, disabled: l, children: e });
15
+ }, K = "_card_awzw5_1", Q = {
16
+ card: K
17
+ }, Ye = (t) => {
18
+ const { children: e, class: n } = t;
19
+ return /* @__PURE__ */ r("div", { class: m(Q.card, n), children: e });
20
+ }, X = "_field_17xwz_1", Y = "_input_17xwz_8 _check-input_4u8pk_32 _focus-ring_4u8pk_3 _disabled_4u8pk_8", Z = "_error_17xwz_12 _field-error_4u8pk_36", q = {
21
+ field: X,
22
+ input: Y,
23
+ error: Z
24
+ }, Ze = (t) => {
25
+ const { label: e, name: n, checked: s, required: l, disabled: c, error: a, onChange: d, class: i } = t, h = f(), p = `${h}-error`;
26
+ return /* @__PURE__ */ b("div", { class: m(q.field, i), children: [
27
+ /* @__PURE__ */ r(
24
28
  "input",
25
29
  {
26
- id: u,
27
- class: C.input,
30
+ id: h,
31
+ class: q.input,
28
32
  type: "checkbox",
29
- name: l,
30
- checked: n,
31
- required: s,
33
+ name: n,
34
+ checked: s,
35
+ required: l,
32
36
  disabled: c,
33
- onChange: o && ((m) => o(m.target.checked))
37
+ "aria-invalid": !!a || void 0,
38
+ "aria-describedby": g(a && p),
39
+ onChange: d && ((u) => d(u.target.checked))
34
40
  }
35
41
  ),
36
- /* @__PURE__ */ a("label", { for: u, children: e })
42
+ /* @__PURE__ */ r("label", { for: h, children: e }),
43
+ a && /* @__PURE__ */ r("p", { id: p, class: q.error, role: "alert", children: a })
37
44
  ] });
38
- }, W = "_link_7wgic_1 _link_4m0e1_22 _focus-ring_4m0e1_3", z = {
39
- link: W
40
- }, Ee = (t) => {
41
- const { href: e, fileName: l, label: n, class: s } = t;
42
- return /* @__PURE__ */ a("a", { href: e, download: l, class: h(z.link, s), children: n });
43
- }, A = "_form_rchcx_1", M = "_actions_rchcx_6", q = {
44
- form: A,
45
- actions: M
46
- }, Be = (t) => {
47
- const { onSubmit: e, submitLabel: l = "Submit", resetLabel: n, children: s, class: c } = t;
48
- return /* @__PURE__ */ _(
45
+ }, ee = "_link_7wgic_1 _link_4u8pk_22 _focus-ring_4u8pk_3", te = {
46
+ link: ee
47
+ }, et = (t) => {
48
+ const { href: e, fileName: n, label: s, class: l } = t;
49
+ return /* @__PURE__ */ r("a", { href: e, download: n, class: m(te.link, l), children: s });
50
+ }, ne = "_form_jr324_1", se = "_actions_jr324_6", le = "_status_jr324_13", L = {
51
+ form: ne,
52
+ actions: se,
53
+ status: le
54
+ }, tt = (t) => {
55
+ const {
56
+ onSubmit: e,
57
+ submitLabel: n = "Submit",
58
+ resetLabel: s,
59
+ status: l,
60
+ children: c,
61
+ class: a
62
+ } = t;
63
+ return /* @__PURE__ */ b(
49
64
  "form",
50
65
  {
51
- class: h(q.form, c),
52
- onSubmit: (o) => {
53
- o.preventDefault();
54
- const d = new FormData(o.currentTarget);
55
- e(d);
66
+ class: m(L.form, a),
67
+ onSubmit: (d) => {
68
+ d.preventDefault();
69
+ const i = new FormData(d.currentTarget);
70
+ e(i);
56
71
  },
57
72
  children: [
58
- s,
59
- /* @__PURE__ */ _("div", { class: q.actions, children: [
60
- /* @__PURE__ */ a(I, { type: "submit", label: l }),
61
- n && /* @__PURE__ */ a(I, { type: "reset", label: n })
62
- ] })
73
+ c,
74
+ /* @__PURE__ */ b("div", { class: L.actions, children: [
75
+ /* @__PURE__ */ r(D, { type: "submit", label: n }),
76
+ s && /* @__PURE__ */ r(D, { type: "reset", label: s })
77
+ ] }),
78
+ l && /* @__PURE__ */ r("output", { class: L.status, children: l })
63
79
  ]
64
80
  }
65
81
  );
66
- }, U = "_field_18ejg_1", V = "_label_18ejg_8", J = "_required_18ejg_12", x = {
67
- field: U,
68
- label: V,
69
- required: J
70
- }, g = (t) => {
71
- const { for: e, label: l, required: n, children: s, class: c } = t;
72
- return /* @__PURE__ */ _("div", { class: h(x.field, c), children: [
73
- /* @__PURE__ */ _("label", { class: x.label, for: e, children: [
74
- l,
82
+ }, re = "_field_7l9ux_1", ae = "_label_7l9ux_8", ce = "_required_7l9ux_12", oe = "_error_7l9ux_16 _field-error_4u8pk_36", S = {
83
+ field: re,
84
+ label: ae,
85
+ required: ce,
86
+ error: oe
87
+ }, w = (t) => {
88
+ const { for: e, label: n, required: s, error: l, errorId: c, children: a, class: d } = t;
89
+ return /* @__PURE__ */ b("div", { class: m(S.field, d), children: [
90
+ /* @__PURE__ */ b("label", { class: S.label, for: e, children: [
91
+ n,
75
92
  ":",
76
- n && /* @__PURE__ */ _("span", { class: x.required, "aria-hidden": "true", children: [
93
+ s && /* @__PURE__ */ b("span", { class: S.required, "aria-hidden": "true", children: [
77
94
  " ",
78
95
  "*"
79
96
  ] })
80
97
  ] }),
81
- s
98
+ a,
99
+ l && /* @__PURE__ */ r("p", { id: c, class: S.error, role: "alert", children: l })
82
100
  ] });
83
- }, K = "_input_1j10x_1 _text-input_4m0e1_13 _focus-ring_4m0e1_3 _disabled_4m0e1_8", Q = {
84
- input: K
85
- }, X = {
101
+ }, ie = "_input_1j10x_1 _text-input_4u8pk_13 _focus-ring_4u8pk_3 _disabled_4u8pk_8", de = {
102
+ input: ie
103
+ }, ue = {
86
104
  email: "email",
87
105
  tel: "tel",
88
106
  url: "url"
89
- }, He = (t) => {
107
+ }, nt = (t) => {
90
108
  const {
91
109
  label: e,
92
- name: l,
93
- type: n = "text",
94
- value: s,
110
+ name: n,
111
+ type: s = "text",
112
+ value: l,
95
113
  placeholder: c,
96
- maxLength: o,
114
+ maxLength: a,
97
115
  autocomplete: d,
98
- readOnly: u,
99
- pattern: m,
100
- required: r,
101
- disabled: i,
102
- onInput: p,
103
- class: f
104
- } = t, v = b();
105
- return /* @__PURE__ */ a(g, { label: e, for: v, required: r, class: f, children: /* @__PURE__ */ a(
106
- "input",
116
+ readOnly: i,
117
+ pattern: h,
118
+ required: p,
119
+ disabled: u,
120
+ error: _,
121
+ onInput: o,
122
+ class: v
123
+ } = t, k = f(), y = `${k}-error`;
124
+ return /* @__PURE__ */ r(
125
+ w,
107
126
  {
108
- id: v,
109
- class: Q.input,
110
- type: n,
111
- name: l,
112
- value: s,
113
- placeholder: c,
114
- maxLength: o,
115
- autoComplete: d ?? X[n],
116
- readOnly: u,
117
- pattern: m,
118
- required: r,
119
- disabled: i,
120
- onInput: p && ((P) => p(P.target.value))
127
+ label: e,
128
+ for: k,
129
+ required: p,
130
+ error: _,
131
+ errorId: y,
132
+ class: v,
133
+ children: /* @__PURE__ */ r(
134
+ "input",
135
+ {
136
+ id: k,
137
+ class: de.input,
138
+ type: s,
139
+ name: n,
140
+ value: l,
141
+ placeholder: c,
142
+ maxLength: a,
143
+ autoComplete: d ?? ue[s],
144
+ readOnly: i,
145
+ pattern: h,
146
+ required: p,
147
+ disabled: u,
148
+ "aria-invalid": !!_ || void 0,
149
+ "aria-describedby": g(_ && y),
150
+ onInput: o && ((I) => o(I.target.value))
151
+ }
152
+ )
121
153
  }
122
- ) });
123
- }, N = $(window.location.pathname), F = $(window.location.hash.slice(1));
124
- function Y(t) {
154
+ );
155
+ }, P = j(window.location.pathname), A = j(window.location.hash.slice(1));
156
+ function _e(t) {
125
157
  const e = t.indexOf("#");
126
- let l = "", n = t;
127
- e >= 0 && (l = t.slice(e + 1), n = t.slice(0, e));
128
- const s = n.indexOf("?");
129
- let c = "", o = n;
130
- return s >= 0 && (c = n.slice(s), o = n.slice(0, s)), { pathname: o || "/", search: c, hash: l };
158
+ let n = "", s = t;
159
+ e >= 0 && (n = t.slice(e + 1), s = t.slice(0, e));
160
+ const l = s.indexOf("?");
161
+ let c = "", a = s;
162
+ return l >= 0 && (c = s.slice(l), a = s.slice(0, l)), { pathname: a || "/", search: c, hash: n };
131
163
  }
132
- function Z(t, e) {
133
- const { pathname: l, search: n, hash: s } = Y(t), c = l + n + (s ? `#${s}` : "");
134
- e?.replace ? history.replaceState(null, "", c) : history.pushState(null, "", c), N.value = l, F.value = s;
164
+ function pe(t, e) {
165
+ const { pathname: n, search: s, hash: l } = _e(t), c = n + s + (l ? `#${l}` : "");
166
+ e?.replace ? history.replaceState(null, "", c) : history.pushState(null, "", c), P.value = n, A.value = l;
135
167
  }
136
168
  window.addEventListener("popstate", () => {
137
- N.value = window.location.pathname, F.value = window.location.hash.slice(1);
169
+ P.value = window.location.pathname, A.value = window.location.hash.slice(1);
138
170
  });
139
- const ee = "_link_7wgic_1 _link_4m0e1_22 _focus-ring_4m0e1_3", S = {
140
- link: ee
171
+ const he = "_link_7wgic_1 _link_4u8pk_22 _focus-ring_4u8pk_3", F = {
172
+ link: he
141
173
  };
142
- function te(t) {
174
+ function be(t) {
143
175
  try {
144
176
  return new URL(t, window.location.href).origin !== window.location.origin;
145
177
  } catch {
146
178
  return !1;
147
179
  }
148
180
  }
149
- const Oe = (t) => {
150
- const { href: e, children: l, external: n, class: s } = t;
151
- return n ?? te(e) ? /* @__PURE__ */ a("a", { href: e, class: h(S.link, s), rel: "noopener noreferrer", children: l }) : /* @__PURE__ */ a(
181
+ const st = (t) => {
182
+ const { href: e, children: n, external: s, class: l } = t;
183
+ return s ?? be(e) ? /* @__PURE__ */ r("a", { href: e, class: m(F.link, l), rel: "noopener noreferrer", children: n }) : /* @__PURE__ */ r(
152
184
  "a",
153
185
  {
154
186
  href: e,
155
- class: h(S.link, s),
156
- onClick: (o) => {
157
- o.preventDefault(), Z(e);
187
+ class: m(F.link, l),
188
+ onClick: (a) => {
189
+ a.preventDefault(), pe(e);
158
190
  },
159
- children: l
191
+ children: n
160
192
  }
161
193
  );
162
- }, se = "_nav_778nl_1", ne = "_title_778nl_6", L = {
163
- nav: se,
164
- title: ne
165
- }, Re = (t) => {
166
- const { title: e, children: l, class: n } = t, s = b();
167
- return /* @__PURE__ */ _("nav", { class: h(L.nav, n), "aria-labelledby": e ? s : void 0, children: [
168
- e && /* @__PURE__ */ a("h2", { id: s, class: L.title, children: e }),
169
- l
194
+ }, me = "_nav_778nl_1", ve = "_title_778nl_6", O = {
195
+ nav: me,
196
+ title: ve
197
+ }, lt = (t) => {
198
+ const { title: e, children: n, class: s } = t, l = f();
199
+ return /* @__PURE__ */ b("nav", { class: m(O.nav, s), "aria-labelledby": e ? l : void 0, children: [
200
+ e && /* @__PURE__ */ r("h2", { id: l, class: O.title, children: e }),
201
+ n
170
202
  ] });
171
- }, le = "_input_1j10x_1 _text-input_4m0e1_13 _focus-ring_4m0e1_3 _disabled_4m0e1_8", ae = {
172
- input: le
173
- }, Ge = (t) => {
203
+ }, fe = "_input_1j10x_1 _text-input_4u8pk_13 _focus-ring_4u8pk_3 _disabled_4u8pk_8", ke = {
204
+ input: fe
205
+ }, rt = (t) => {
174
206
  const {
175
207
  label: e,
176
- name: l,
177
- min: n,
178
- max: s,
208
+ name: n,
209
+ min: s,
210
+ max: l,
179
211
  step: c,
180
- value: o,
212
+ value: a,
181
213
  placeholder: d,
182
- required: u,
183
- disabled: m,
184
- onInput: r,
185
- class: i
186
- } = t, p = b();
187
- return /* @__PURE__ */ a(g, { label: e, for: p, required: u, class: i, children: /* @__PURE__ */ a(
188
- "input",
214
+ required: i,
215
+ disabled: h,
216
+ error: p,
217
+ onInput: u,
218
+ class: _
219
+ } = t, o = f(), v = `${o}-error`;
220
+ return /* @__PURE__ */ r(
221
+ w,
189
222
  {
190
- id: p,
191
- class: ae.input,
192
- type: "number",
193
- name: l,
194
- min: n,
195
- max: s,
196
- step: c,
197
- value: o,
198
- placeholder: d,
199
- required: u,
200
- disabled: m,
201
- onInput: r && ((f) => r(f.target.valueAsNumber))
223
+ label: e,
224
+ for: o,
225
+ required: i,
226
+ error: p,
227
+ errorId: v,
228
+ class: _,
229
+ children: /* @__PURE__ */ r(
230
+ "input",
231
+ {
232
+ id: o,
233
+ class: ke.input,
234
+ type: "number",
235
+ name: n,
236
+ min: s,
237
+ max: l,
238
+ step: c,
239
+ value: a,
240
+ placeholder: d,
241
+ required: i,
242
+ disabled: h,
243
+ "aria-invalid": !!p || void 0,
244
+ "aria-describedby": g(p && v),
245
+ onInput: u && ((k) => u(k.target.valueAsNumber))
246
+ }
247
+ )
202
248
  }
203
- ) });
204
- }, ce = "_wrapper_1mu6v_1", oe = "_input_1mu6v_6 _text-input_4m0e1_13 _focus-ring_4m0e1_3 _disabled_4m0e1_8", ie = "_toggle_1mu6v_13 _focus-ring_4m0e1_3 _disabled_4m0e1_8", y = {
205
- wrapper: ce,
206
- input: oe,
207
- toggle: ie
208
- }, re = {
249
+ );
250
+ }, ge = "_wrapper_1mu6v_1", ye = "_input_1mu6v_6 _text-input_4u8pk_13 _focus-ring_4u8pk_3 _disabled_4u8pk_8", $e = "_toggle_1mu6v_13 _focus-ring_4u8pk_3 _disabled_4u8pk_8", T = {
251
+ wrapper: ge,
252
+ input: ye,
253
+ toggle: $e
254
+ }, xe = {
209
255
  current: "current-password",
210
256
  new: "new-password"
211
- }, We = (t) => {
257
+ }, at = (t) => {
212
258
  const {
213
259
  label: e,
214
- name: l,
215
- purpose: n,
216
- value: s,
260
+ name: n,
261
+ purpose: s,
262
+ value: l,
217
263
  placeholder: c,
218
- required: o,
264
+ required: a,
219
265
  disabled: d,
220
- onInput: u,
221
- class: m
222
- } = t, r = b(), i = j(!1);
223
- return /* @__PURE__ */ a(g, { label: e, for: r, required: o, class: m, children: /* @__PURE__ */ _("div", { class: y.wrapper, children: [
224
- /* @__PURE__ */ a(
225
- "input",
226
- {
227
- id: r,
228
- class: y.input,
229
- type: i.value ? "text" : "password",
230
- name: l,
231
- value: s,
232
- placeholder: c,
233
- autoComplete: re[n],
234
- required: o,
235
- disabled: d,
236
- onInput: u && ((p) => u(p.target.value))
237
- }
238
- ),
239
- /* @__PURE__ */ a(
240
- "button",
241
- {
242
- type: "button",
243
- class: y.toggle,
244
- disabled: d,
245
- onClick: () => {
246
- i.value = !i.value;
247
- },
248
- children: i.value ? "Hide password" : "Show password"
249
- }
250
- )
251
- ] }) });
252
- }, de = "_fieldset_19vke_1", ue = "_legend_19vke_6", _e = "_option_19vke_11", pe = "_input_19vke_19 _check-input_4m0e1_32 _focus-ring_4m0e1_3", w = {
253
- fieldset: de,
254
- legend: ue,
255
- option: _e,
256
- input: pe
257
- }, ze = (t) => {
258
- const { legend: e, name: l, options: n, value: s, required: c, disabled: o, onChange: d, class: u } = t, m = b();
259
- return /* @__PURE__ */ _("fieldset", { class: h(w.fieldset, u), children: [
260
- /* @__PURE__ */ a("legend", { class: w.legend, children: e }),
261
- n.map((r) => {
262
- const i = `${m}-${r.value}`;
263
- return /* @__PURE__ */ _("div", { class: w.option, children: [
264
- /* @__PURE__ */ a(
266
+ error: i,
267
+ onInput: h,
268
+ class: p
269
+ } = t, u = f(), _ = `${u}-error`, o = x(!1);
270
+ return /* @__PURE__ */ r(
271
+ w,
272
+ {
273
+ label: e,
274
+ for: u,
275
+ required: a,
276
+ error: i,
277
+ errorId: _,
278
+ class: p,
279
+ children: /* @__PURE__ */ b("div", { class: T.wrapper, children: [
280
+ /* @__PURE__ */ r(
265
281
  "input",
266
282
  {
267
- id: i,
268
- class: w.input,
269
- type: "radio",
270
- name: l,
271
- value: r.value,
272
- checked: s === r.value,
273
- required: c,
274
- disabled: o,
275
- onChange: d && (() => d(r.value))
283
+ id: u,
284
+ class: T.input,
285
+ type: o.value ? "text" : "password",
286
+ name: n,
287
+ value: l,
288
+ placeholder: c,
289
+ autoComplete: xe[s],
290
+ required: a,
291
+ disabled: d,
292
+ "aria-invalid": !!i || void 0,
293
+ "aria-describedby": g(i && _),
294
+ onInput: h && ((v) => h(v.target.value))
276
295
  }
277
296
  ),
278
- /* @__PURE__ */ a("label", { for: i, children: r.label })
279
- ] }, r.value);
280
- })
281
- ] });
282
- }, Ae = (t) => {
283
- const { path: e, children: l } = t, n = N.value;
297
+ /* @__PURE__ */ r(
298
+ "button",
299
+ {
300
+ type: "button",
301
+ class: T.toggle,
302
+ disabled: d,
303
+ onClick: () => {
304
+ o.value = !o.value;
305
+ },
306
+ children: o.value ? "Hide password" : "Show password"
307
+ }
308
+ )
309
+ ] })
310
+ }
311
+ );
312
+ }, we = "_fieldset_lymkd_1", Ie = "_legend_lymkd_6", Ne = "_option_lymkd_11", Ce = "_input_lymkd_19 _check-input_4u8pk_32 _focus-ring_4u8pk_3", Se = "_error_lymkd_23 _field-error_4u8pk_36", $ = {
313
+ fieldset: we,
314
+ legend: Ie,
315
+ option: Ne,
316
+ input: Ce,
317
+ error: Se
318
+ }, ct = (t) => {
319
+ const {
320
+ legend: e,
321
+ name: n,
322
+ options: s,
323
+ value: l,
324
+ required: c,
325
+ disabled: a,
326
+ error: d,
327
+ onChange: i,
328
+ class: h
329
+ } = t, p = f(), u = `${p}-error`;
330
+ return /* @__PURE__ */ b(
331
+ "fieldset",
332
+ {
333
+ class: m($.fieldset, h),
334
+ "aria-invalid": !!d || void 0,
335
+ "aria-describedby": g(d && u),
336
+ children: [
337
+ /* @__PURE__ */ r("legend", { class: $.legend, children: e }),
338
+ s.map((_) => {
339
+ const o = `${p}-${_.value}`;
340
+ return /* @__PURE__ */ b("div", { class: $.option, children: [
341
+ /* @__PURE__ */ r(
342
+ "input",
343
+ {
344
+ id: o,
345
+ class: $.input,
346
+ type: "radio",
347
+ name: n,
348
+ value: _.value,
349
+ checked: l === _.value,
350
+ required: c,
351
+ disabled: a,
352
+ onChange: i && (() => i(_.value))
353
+ }
354
+ ),
355
+ /* @__PURE__ */ r("label", { for: o, children: _.label })
356
+ ] }, _.value);
357
+ }),
358
+ d && /* @__PURE__ */ r("p", { id: u, class: $.error, role: "alert", children: d })
359
+ ]
360
+ }
361
+ );
362
+ }, ot = (t) => {
363
+ const { path: e, children: n } = t, s = P.value;
284
364
  if (e.endsWith("/*")) {
285
- const s = e.slice(0, -1);
286
- if (!n.startsWith(s) && n !== s.slice(0, -1))
365
+ const l = e.slice(0, -1);
366
+ if (!s.startsWith(l) && s !== l.slice(0, -1))
287
367
  return null;
288
- } else if (n !== e)
368
+ } else if (s !== e)
289
369
  return null;
290
- return /* @__PURE__ */ a(T, { children: l });
291
- }, he = "_section_4nogy_1", me = {
292
- section: he
293
- }, Me = (t) => {
294
- const { title: e, level: l = 2, children: n, class: s } = t, c = b(), o = `h${l}`;
295
- return /* @__PURE__ */ _("section", { class: h(me.section, s), "aria-labelledby": c, children: [
296
- /* @__PURE__ */ a(o, { id: c, children: e }),
297
- n
370
+ return /* @__PURE__ */ r(W, { children: n });
371
+ }, qe = "_section_4nogy_1", Le = {
372
+ section: qe
373
+ }, it = (t) => {
374
+ const { title: e, level: n = 2, children: s, class: l } = t, c = f(), a = `h${n}`;
375
+ return /* @__PURE__ */ b("section", { class: m(Le.section, l), "aria-labelledby": c, children: [
376
+ /* @__PURE__ */ r(a, { id: c, children: e }),
377
+ s
298
378
  ] });
299
- }, be = "_select_1cxnx_1 _text-input_4m0e1_13 _focus-ring_4m0e1_3 _disabled_4m0e1_8", fe = {
300
- select: be
301
- }, ve = (t) => "options" in t, Ue = (t) => {
379
+ }, Te = "_select_1cxnx_1 _text-input_4u8pk_13 _focus-ring_4u8pk_3 _disabled_4u8pk_8", Ee = {
380
+ select: Te
381
+ }, je = (t) => "options" in t, dt = (t) => {
302
382
  const {
303
383
  label: e,
304
- name: l,
305
- value: n,
306
- placeholder: s,
384
+ name: n,
385
+ value: s,
386
+ placeholder: l,
307
387
  options: c,
308
- required: o,
388
+ required: a,
309
389
  disabled: d,
310
- onChange: u,
311
- class: m
312
- } = t, r = b();
313
- return /* @__PURE__ */ a(g, { label: e, for: r, required: o, class: m, children: /* @__PURE__ */ _(
314
- "select",
390
+ error: i,
391
+ onChange: h,
392
+ class: p
393
+ } = t, u = f(), _ = `${u}-error`;
394
+ return /* @__PURE__ */ r(
395
+ w,
315
396
  {
316
- id: r,
317
- class: fe.select,
318
- name: l,
319
- value: n,
320
- required: o,
321
- disabled: d,
322
- onChange: u && ((i) => u(i.target.value)),
323
- children: [
324
- s && /* @__PURE__ */ a("option", { value: "", disabled: !0, children: s }),
325
- c.map(
326
- (i) => ve(i) ? /* @__PURE__ */ a("optgroup", { label: i.label, children: i.options.map((p) => /* @__PURE__ */ a("option", { value: p.value, children: p.label }, p.value)) }, i.label) : /* @__PURE__ */ a("option", { value: i.value, children: i.label }, i.value)
327
- )
328
- ]
397
+ label: e,
398
+ for: u,
399
+ required: a,
400
+ error: i,
401
+ errorId: _,
402
+ class: p,
403
+ children: /* @__PURE__ */ b(
404
+ "select",
405
+ {
406
+ id: u,
407
+ class: Ee.select,
408
+ name: n,
409
+ value: s,
410
+ required: a,
411
+ disabled: d,
412
+ "aria-invalid": !!i || void 0,
413
+ "aria-describedby": g(i && _),
414
+ onChange: h && ((o) => h(o.target.value)),
415
+ children: [
416
+ l && /* @__PURE__ */ r("option", { value: "", disabled: !0, children: l }),
417
+ c.map(
418
+ (o) => je(o) ? /* @__PURE__ */ r("optgroup", { label: o.label, children: o.options.map((v) => /* @__PURE__ */ r("option", { value: v.value, children: v.label }, v.value)) }, o.label) : /* @__PURE__ */ r("option", { value: o.value, children: o.label }, o.value)
419
+ )
420
+ ]
421
+ }
422
+ )
329
423
  }
330
- ) });
331
- }, ge = "_skip_xbsul_1 _focus-ring_4m0e1_3", we = {
332
- skip: ge
333
- }, Ve = (t) => {
334
- const { target: e = "#main", label: l = "Skip to main content", class: n } = t;
335
- return /* @__PURE__ */ a("a", { href: e, class: h(we.skip, n), children: l });
336
- }, xe = "_table_roeo7_1", ye = {
337
- table: xe
338
- }, Je = (t) => {
339
- const { headers: e, data: l, class: n } = t;
340
- return /* @__PURE__ */ _("table", { class: h(ye.table, n), children: [
341
- /* @__PURE__ */ a("thead", { children: /* @__PURE__ */ a("tr", { children: e.map((s, c) => /* @__PURE__ */ a("th", { scope: "col", children: s }, `${s}-${c}`)) }) }),
342
- /* @__PURE__ */ a("tbody", { children: l.map((s, c) => /* @__PURE__ */ a("tr", { children: s.map((o, d) => /* @__PURE__ */ a("td", { children: o }, `${e[d]}-${c}-${d}`)) }, c)) })
424
+ );
425
+ }, Pe = "_skip_xbsul_1 _focus-ring_4u8pk_3", He = {
426
+ skip: Pe
427
+ }, ut = (t) => {
428
+ const { target: e = "#main", label: n = "Skip to main content", class: s } = t;
429
+ return /* @__PURE__ */ r("a", { href: e, class: m(He.skip, s), children: n });
430
+ }, Be = "_table_dls60_1", De = "_caption_dls60_6", R = {
431
+ table: Be,
432
+ caption: De
433
+ }, _t = (t) => {
434
+ const { caption: e, headers: n, data: s, class: l } = t;
435
+ return /* @__PURE__ */ b("table", { class: m(R.table, l), children: [
436
+ /* @__PURE__ */ r("caption", { class: R.caption, children: e }),
437
+ /* @__PURE__ */ r("thead", { children: /* @__PURE__ */ r("tr", { children: n.map((c, a) => /* @__PURE__ */ r("th", { scope: "col", children: c }, `${c}-${a}`)) }) }),
438
+ /* @__PURE__ */ r("tbody", { children: s.map((c, a) => /* @__PURE__ */ r("tr", { children: c.map((d, i) => /* @__PURE__ */ r("td", { children: d }, `${n[i]}-${a}-${i}`)) }, a)) })
343
439
  ] });
344
- }, ke = "_wrapper_1kyv1_1", $e = "_textarea_1kyv1_6 _text-input_4m0e1_13 _focus-ring_4m0e1_3 _disabled_4m0e1_8", Ne = "_counter_1kyv1_11", k = {
345
- wrapper: ke,
346
- textarea: $e,
347
- counter: Ne
348
- }, Ke = (t) => {
440
+ }, Fe = "_hidden_19nib_1 _visually-hidden_4u8pk_42", Oe = {
441
+ hidden: Fe
442
+ }, Re = (t) => {
443
+ const { children: e } = t;
444
+ return /* @__PURE__ */ r("span", { class: Oe.hidden, children: e });
445
+ }, ze = "_wrapper_1kyv1_1", Ae = "_textarea_1kyv1_6 _text-input_4u8pk_13 _focus-ring_4u8pk_3 _disabled_4u8pk_8", Ue = "_counter_1kyv1_11", E = {
446
+ wrapper: ze,
447
+ textarea: Ae,
448
+ counter: Ue
449
+ }, z = [75, 90, 100], Ge = 10;
450
+ function We(t) {
451
+ for (let e = z.length - 1; e >= 0; e--) {
452
+ const n = z[e];
453
+ if (n !== void 0 && t >= n)
454
+ return n;
455
+ }
456
+ return 0;
457
+ }
458
+ const pt = (t) => {
349
459
  const {
350
460
  label: e,
351
- name: l,
352
- maxChars: n,
353
- value: s,
461
+ name: n,
462
+ maxChars: s,
463
+ value: l,
354
464
  placeholder: c,
355
- required: o,
465
+ required: a,
356
466
  disabled: d,
357
- onInput: u,
358
- class: m
359
- } = t, r = b(), i = `${r}-counter`, p = j(s?.length ?? 0);
360
- return /* @__PURE__ */ a(g, { label: e, for: r, required: o, class: m, children: /* @__PURE__ */ _("div", { class: k.wrapper, children: [
361
- /* @__PURE__ */ a(
362
- "textarea",
363
- {
364
- id: r,
365
- class: k.textarea,
366
- name: l,
367
- maxLength: n,
368
- placeholder: c,
369
- required: o,
370
- disabled: d,
371
- "aria-describedby": i,
372
- onInput: (f) => {
373
- const v = f.target.value;
374
- p.value = v.length, u?.(v);
375
- },
376
- children: s
377
- }
378
- ),
379
- /* @__PURE__ */ _("span", { id: i, class: k.counter, children: [
380
- p,
381
- " / ",
382
- n
383
- ] })
384
- ] }) });
385
- }, Ie = "_theme_13mb7_1", Ce = {
386
- theme: Ie
387
- }, Qe = (t) => {
388
- const { children: e, class: l } = t;
389
- return /* @__PURE__ */ a("div", { class: h(Ce.theme, l), children: e });
390
- }, qe = "_hidden_19nib_1 _visually-hidden_4m0e1_36", Se = {
391
- hidden: qe
392
- }, Xe = (t) => {
393
- const { children: e } = t;
394
- return /* @__PURE__ */ a("span", { class: Se.hidden, children: e });
395
- }, Le = $(document.title);
396
- D(() => {
397
- document.title = Le.value;
467
+ error: i,
468
+ onInput: h,
469
+ class: p
470
+ } = t, u = f(), _ = `${u}-error`, o = `${u}-counter`, v = x(l?.length ?? 0), k = x(""), y = x(0), I = x(!1);
471
+ return /* @__PURE__ */ r(
472
+ w,
473
+ {
474
+ label: e,
475
+ for: u,
476
+ required: a,
477
+ error: i,
478
+ errorId: _,
479
+ class: p,
480
+ children: /* @__PURE__ */ b("div", { class: E.wrapper, children: [
481
+ /* @__PURE__ */ r(
482
+ "textarea",
483
+ {
484
+ id: u,
485
+ class: E.textarea,
486
+ name: n,
487
+ maxLength: s,
488
+ placeholder: c,
489
+ required: a,
490
+ disabled: d,
491
+ "aria-invalid": !!i || void 0,
492
+ "aria-describedby": g(i && _, o),
493
+ onInput: (U) => {
494
+ const N = U.target.value;
495
+ v.value = N.length;
496
+ const C = s - N.length, G = N.length / s * 100, H = We(G), B = !I.value && C <= Ge && C > 0;
497
+ (H > y.value || B) && (k.value = `${C} character${C === 1 ? "" : "s"} remaining`, y.value = H, B && (I.value = !0)), h?.(N);
498
+ },
499
+ children: l
500
+ }
501
+ ),
502
+ /* @__PURE__ */ b("span", { id: o, class: E.counter, children: [
503
+ v,
504
+ " / ",
505
+ s
506
+ ] }),
507
+ /* @__PURE__ */ r(Re, { children: /* @__PURE__ */ r("span", { "aria-live": "polite", children: k }) })
508
+ ] })
509
+ }
510
+ );
511
+ }, Me = "_theme_13mb7_1", Ve = {
512
+ theme: Me
513
+ }, ht = (t) => {
514
+ const { children: e, class: n } = t;
515
+ return /* @__PURE__ */ r("div", { class: m(Ve.theme, n), children: e });
516
+ }, Je = j(document.title);
517
+ M(() => {
518
+ document.title = Je.value;
398
519
  });
399
520
  export {
400
- I as Button,
401
- Te as Card,
402
- De as Checkbox,
403
- Ee as DownloadLink,
404
- Be as Form,
405
- He as Input,
406
- Oe as Link,
407
- Re as Nav,
408
- Ge as NumberInput,
409
- We as PasswordInput,
410
- ze as RadioGroup,
411
- Ae as Route,
412
- Me as Section,
413
- Ue as Select,
414
- Ve as SkipLink,
415
- Je as Table,
416
- Ke as Textarea,
417
- Qe as Theme,
418
- Xe as VisuallyHidden,
419
- h as cx,
420
- F as hash,
421
- N as location,
422
- Z as navigate,
423
- Le as title
521
+ D as Button,
522
+ Ye as Card,
523
+ Ze as Checkbox,
524
+ et as DownloadLink,
525
+ tt as Form,
526
+ nt as Input,
527
+ st as Link,
528
+ lt as Nav,
529
+ rt as NumberInput,
530
+ at as PasswordInput,
531
+ ct as RadioGroup,
532
+ ot as Route,
533
+ it as Section,
534
+ dt as Select,
535
+ ut as SkipLink,
536
+ _t as Table,
537
+ pt as Textarea,
538
+ ht as Theme,
539
+ Re as VisuallyHidden,
540
+ m as cx,
541
+ A as hash,
542
+ P as location,
543
+ pe as navigate,
544
+ Je as title
424
545
  };
@@ -8,6 +8,8 @@ interface IFormProps extends IBaseProps {
8
8
  submitLabel?: string;
9
9
  /** Label for the optional reset button. Omit to hide. */
10
10
  resetLabel?: string;
11
+ /** Status message displayed after submission (e.g., success/failure feedback). */
12
+ status?: string;
11
13
  /** Form field children. */
12
14
  children: ComponentChildren;
13
15
  }
@@ -8,6 +8,10 @@ interface IFormFieldProps extends IBaseProps {
8
8
  for: string;
9
9
  /** Whether the field shows a required indicator. Accepts `undefined` for prop forwarding. */
10
10
  required?: boolean | undefined;
11
+ /** Error message to display below the input. Accepts `undefined` for prop forwarding. */
12
+ error?: string | undefined;
13
+ /** ID for the error message element (used for aria-describedby on the input). Accepts `undefined` for prop forwarding. */
14
+ errorId?: string | undefined;
11
15
  /** Field input element(s). */
12
16
  children: ComponentChildren;
13
17
  }
@@ -21,6 +21,8 @@ interface IRadioGroupProps extends IBaseProps {
21
21
  required?: boolean;
22
22
  /** Whether the group is disabled. */
23
23
  disabled?: boolean;
24
+ /** Error message. When set, renders an error message and marks the fieldset as invalid. */
25
+ error?: string;
24
26
  /** Called with the selected value on change. */
25
27
  onChange?: (value: string) => void;
26
28
  }
@@ -2,6 +2,8 @@ import { IBaseProps } from '../scripts/types';
2
2
  import { ComponentChildren, FunctionComponent } from 'preact';
3
3
  /** Props for {@link Table}. */
4
4
  interface ITableProps extends IBaseProps {
5
+ /** Accessible table name. Rendered as a `<caption>` element. */
6
+ caption: string;
5
7
  /** Column header labels. */
6
8
  headers: string[];
7
9
  /** Row data as a 2D array of renderable content. */
@@ -13,4 +13,6 @@ export interface IFieldProps extends IBaseProps {
13
13
  required?: boolean;
14
14
  /** Whether the field is disabled. */
15
15
  disabled?: boolean;
16
+ /** Error message. When set, renders an error message and marks the field as invalid. */
17
+ error?: string;
16
18
  }
@@ -33,3 +33,21 @@
33
33
  * @returns Space-separated class string, or empty string if no truthy values.
34
34
  */
35
35
  export declare function cx(...classes: (string | false | undefined)[]): string;
36
+ /**
37
+ * Compose `aria-describedby` from a list of element IDs, filtering falsy values.
38
+ *
39
+ * Returns `undefined` when no truthy IDs remain — this keeps the attribute off the
40
+ * element entirely rather than rendering an empty string.
41
+ *
42
+ * @example
43
+ * // Single description
44
+ * describeBy(error && errorId) // "field-error" | undefined
45
+ *
46
+ * @example
47
+ * // Multiple descriptions
48
+ * describeBy(error && errorId, counterId) // "field-error counter" | undefined
49
+ *
50
+ * @param ids - IDs to compose. `false` and `undefined` values are filtered out.
51
+ * @returns Space-separated ID string, or `undefined` if empty.
52
+ */
53
+ export declare function describeBy(...ids: (string | false | undefined)[]): string | undefined;
package/package.json CHANGED
@@ -1,12 +1,28 @@
1
1
  {
2
2
  "name": "@auldrant/ui",
3
- "version": "0.0.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "description": "Accessible Preact component library with design tokens and CSS modules",
6
6
  "author": "Colonel Jade",
7
7
  "license": "MIT",
8
- "keywords": ["preact", "components", "ui", "component-library", "accessibility", "a11y", "css-modules", "design-tokens", "typescript"],
9
- "publishConfig": { "access": "public" },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/coloneljade/auldrant-ui"
11
+ },
12
+ "keywords": [
13
+ "preact",
14
+ "components",
15
+ "ui",
16
+ "component-library",
17
+ "accessibility",
18
+ "a11y",
19
+ "css-modules",
20
+ "design-tokens",
21
+ "typescript"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
10
26
  "module": "./dist/auldrant-ui.js",
11
27
  "types": "./dist/index.d.ts",
12
28
  "exports": {
@@ -19,8 +35,7 @@
19
35
  "files": [
20
36
  "dist",
21
37
  "README.md",
22
- "LICENSE",
23
- "CHANGELOG.md"
38
+ "LICENSE"
24
39
  ],
25
40
  "sideEffects": [
26
41
  "**/*.css"
package/CHANGELOG.md DELETED
@@ -1,58 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/).
7
-
8
- ## [0.4.0] - 2026-02-26
9
-
10
- ### Added
11
-
12
- - **feat(test)**: add axe-core a11y test suite (19 files, setup helpers, 18 test files) ([#20](https://github.com/coloneljade/auldrant-ui/pull/20))
13
- - **refactor(test)**: migrate a11y assertions out of behavioral tests (cleanup + deletions) ([#20](https://github.com/coloneljade/auldrant-ui/pull/20))
14
- - **docs(rules)**: mandate AAA comments and WCAG SC references in tests ([#20](https://github.com/coloneljade/auldrant-ui/pull/20))
15
-
16
- ## [0.3.0] - 2026-02-25
17
-
18
- ### Added
19
-
20
- - Configure Vite, TypeScript, Biome, devcontainer, and test setup ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
21
- - Add routing and title signals for SPA navigation ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
22
- - Shared types, utilities, and composable CSS classes ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
23
- - Semantic HTML-first — native elements before ARIA ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
24
- - CSS Grid layout, em-based spacing, CSS modules ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
25
- - Accessible form field management (`FormField` wrapper) ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
26
- - SkipLink and Nav for keyboard navigation ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
27
- - Type-safe component props (TypeScript strict mode) ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
28
- - Comprehensive test coverage (114 tests) ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
29
- - Pit of success design principle for component APIs ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
30
- - Binary tools principle (Biome fixes, not manual edits) ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
31
- - Mandatory skills workflow (staging, pushing, PRs) ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
32
- - Import aliases (`@components`, `@scripts`, `@signals`, `@styles`) ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
33
- - **Head component** — meta/document head management (issue #18) ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
34
- - **Form data typing** — generic type parameter for typed onSubmit (issue #8) ([#7](https://github.com/coloneljade/auldrant-ui/pull/7))
35
-
36
- ## [0.2.0] - 2026-02-24
37
-
38
- ### Added
39
-
40
- - Remove CJS output and UMD name — ESM-only library ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
41
- - Fix CI publish failure by skipping lefthook in CI environment ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
42
- - Add `@components` and `@styles` import path aliases (tsconfig + vite) ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
43
- - Add GitHub CLI feature and YAML extension to devcontainer ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
44
- - Create VSCode tasks for all project scripts (test, build, check, typecheck, storybook) ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
45
- - Add component base types (BaseProps, FieldProps) and cx() class utility ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
46
-
47
- ## [0.1.0] - 2026-02-24
48
-
49
- ### Added
50
-
51
- - Remove CJS output and UMD name — ESM-only library ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
52
- - Fix CI publish failure by skipping lefthook in CI environment ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
53
- - Add `@components` and `@styles` import path aliases (tsconfig + vite) ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
54
- - Add GitHub CLI feature and YAML extension to devcontainer ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
55
- - Create VSCode tasks for all project scripts (test, build, check, typecheck, storybook) ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
56
- - Add component base types (BaseProps, FieldProps) and cx() class utility ([#6](https://github.com/coloneljade/auldrant-ui/pull/6))
57
-
58
- ## [Unreleased]