@a4ui/core 0.35.2 → 0.36.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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const A4UI_VERSION = "0.35.2";
1
+ export declare const A4UI_VERSION = "0.36.0";
2
2
  export { cn } from './lib/cn';
3
3
  export { useTheme, toggleTheme, setTheme, storedTheme, applyTheme, toggled, type Theme } from './lib/theme';
4
4
  export { useEffects, isCalm, setEffects } from './lib/effects';
package/dist/index.js CHANGED
@@ -1601,17 +1601,27 @@ function M$(e) {
1601
1601
  })), l;
1602
1602
  })();
1603
1603
  }
1604
- var mi = /* @__PURE__ */ x('<div class="w-full overflow-x-auto"><table>'), hi = /* @__PURE__ */ x("<thead>"), vi = /* @__PURE__ */ x("<tbody>"), bi = /* @__PURE__ */ x("<tr>"), xi = /* @__PURE__ */ x("<th>"), $i = /* @__PURE__ */ x("<td>");
1604
+ var mi = /* @__PURE__ */ x('<div class="relative w-full overflow-x-auto"><table>'), hi = /* @__PURE__ */ x("<thead>"), vi = /* @__PURE__ */ x("<tbody>"), bi = /* @__PURE__ */ x("<tr>"), xi = /* @__PURE__ */ x("<th>"), $i = /* @__PURE__ */ x("<td>");
1605
1605
  function vr(e) {
1606
1606
  const [t, n] = de(e, ["class", "children"]);
1607
- return (() => {
1608
- var r = mi(), l = r.firstChild;
1609
- return ue(l, ge({
1610
- get class() {
1611
- return S("w-full border-collapse text-sm", t.class);
1612
- }
1613
- }, n), !1, !0), u(l, () => t.children), r;
1614
- })();
1607
+ return (
1608
+ // `relative` is load-bearing, not decoration: `overflow` only clips a
1609
+ // descendant whose containing block is inside the scroller. Without a
1610
+ // positioned wrapper, an absolutely-positioned descendant (a
1611
+ // screen-reader-only input inside a cell control, for instance) resolves
1612
+ // against an ancestor further up, escapes the clip at the table's full
1613
+ // scroll width, and drags the whole DOCUMENT into horizontal scrolling —
1614
+ // measured on a phone: a 356 px table inside a 390 px viewport pushed the
1615
+ // page to 413 px.
1616
+ (() => {
1617
+ var r = mi(), l = r.firstChild;
1618
+ return ue(l, ge({
1619
+ get class() {
1620
+ return S("w-full border-collapse text-sm", t.class);
1621
+ }
1622
+ }, n), !1, !0), u(l, () => t.children), r;
1623
+ })()
1624
+ );
1615
1625
  }
1616
1626
  function Rt(e) {
1617
1627
  const [t, n] = de(e, ["class", "children"]);
@@ -4354,8 +4364,12 @@ function Cy(e) {
4354
4364
  onInput: (k) => {
4355
4365
  n(k), a(1);
4356
4366
  },
4357
- placeholder: "Filter…",
4358
- "aria-label": "Filter rows"
4367
+ get placeholder() {
4368
+ return e.filterPlaceholder ?? "Filter…";
4369
+ },
4370
+ get "aria-label"() {
4371
+ return e.filterLabel ?? "Filter rows";
4372
+ }
4359
4373
  })), w;
4360
4374
  })();
4361
4375
  })(), null), u(b, i(vr, {
@@ -4419,7 +4433,8 @@ function Cy(e) {
4419
4433
  },
4420
4434
  onChange: a,
4421
4435
  get summary() {
4422
- return `${f().length} rows`;
4436
+ var y;
4437
+ return ((y = e.rowsSummary) == null ? void 0 : y.call(e, f().length)) ?? `${f().length} rows`;
4423
4438
  }
4424
4439
  }), null), _(() => A(b, S("flex w-full flex-col rounded-lg border border-border bg-background", e.class))), b;
4425
4440
  })();
@@ -10909,7 +10924,7 @@ function Uh(e) {
10909
10924
  })();
10910
10925
  }
10911
10926
  G(["pointerdown"]);
10912
- var Vh = /* @__PURE__ */ x('<div><div class="flex gap-2"><input type=text placeholder="Location label"class="h-9 flex-1 rounded-md border border-border bg-input px-3 text-sm text-foreground placeholder:text-muted-foreground focus:ring-2 focus:ring-ring focus:outline-none">');
10927
+ var Vh = /* @__PURE__ */ x('<div><div class="flex gap-2"><input type=text class="h-9 flex-1 rounded-md border border-border bg-input px-3 text-sm text-foreground placeholder:text-muted-foreground focus:ring-2 focus:ring-ring focus:outline-none">');
10913
10928
  const Kh = 12, Gh = 240;
10914
10929
  function Dw(e) {
10915
10930
  const [t, n] = N(e.value ?? {
@@ -10951,7 +10966,9 @@ function Dw(e) {
10951
10966
  var c = Vh(), d = c.firstChild, f = d.firstChild;
10952
10967
  return f.$$input = (m) => a(m.currentTarget.value), u(d, i(ce, {
10953
10968
  variant: "outline",
10954
- "aria-label": "Use my location",
10969
+ get "aria-label"() {
10970
+ return e.geolocateLabel ?? "Use my location";
10971
+ },
10955
10972
  onClick: o,
10956
10973
  get children() {
10957
10974
  return i(po, {
@@ -10971,7 +10988,13 @@ function Dw(e) {
10971
10988
  return g();
10972
10989
  },
10973
10990
  onClick: s
10974
- }), null), _(() => A(c, S("flex flex-col gap-2", e.class))), _(() => f.value = r().label ?? ""), c;
10991
+ }), null), _((m) => {
10992
+ var h = S("flex flex-col gap-2", e.class), $ = e.labelPlaceholder ?? "Location label";
10993
+ return h !== m.e && A(c, m.e = h), $ !== m.t && I(f, "placeholder", m.t = $), m;
10994
+ }, {
10995
+ e: void 0,
10996
+ t: void 0
10997
+ }), _(() => f.value = r().label ?? ""), c;
10975
10998
  })();
10976
10999
  }
10977
11000
  G(["input"]);
@@ -14838,7 +14861,7 @@ function j1() {
14838
14861
  }
14839
14862
  Tx(e && jl(e) || br);
14840
14863
  }
14841
- const D1 = "0.35.2";
14864
+ const D1 = "0.36.0";
14842
14865
  export {
14843
14866
  D1 as A4UI_VERSION,
14844
14867
  g$ as Accordion,
@@ -18,6 +18,18 @@ export interface DataGridProps {
18
18
  pageSize?: number;
19
19
  /** Show the global text filter above the table. Defaults to true. */
20
20
  filterable?: boolean;
21
+ /**
22
+ * Copy overrides, for apps that do not run in English. Every user-visible
23
+ * string this component renders on its own is here; without them a Spanish
24
+ * or French page shows "Filter…" and "12 rows" in the middle of its own
25
+ * table with no way to change it.
26
+ * @default 'Filter…'
27
+ */
28
+ filterPlaceholder?: string;
29
+ /** Accessible name for the filter box. @default 'Filter rows' */
30
+ filterLabel?: string;
31
+ /** Builds the row-count summary. @default (n) => `${n} rows` */
32
+ rowsSummary?: (count: number) => string;
21
33
  class?: string;
22
34
  }
23
35
  /**
@@ -9,6 +9,15 @@ export interface LocationPickerProps {
9
9
  value?: LocationValue;
10
10
  /** Fires with the full value whenever the label, the pin, or geolocation changes it. */
11
11
  onChange?: (v: LocationValue) => void;
12
+ /**
13
+ * Placeholder for the free-text label field. Overridable because this was
14
+ * hardcoded English inside an otherwise fully translatable component — a
15
+ * Spanish form showed "Location label" in the middle of its own wizard.
16
+ * @default 'Location label'
17
+ */
18
+ labelPlaceholder?: string;
19
+ /** Accessible name for the "use my location" button. @default 'Use my location' */
20
+ geolocateLabel?: string;
12
21
  class?: string;
13
22
  }
14
23
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a4ui/core",
3
- "version": "0.35.2",
3
+ "version": "0.36.0",
4
4
  "description": "A4ui — Spatial Glass design system & component library for SolidJS (Kobalte behavior + Tailwind glass tokens + motion).",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  // import '@a4ui/core/styles.css'
9
9
  // import { Button, Card, Modal } from '@a4ui/core'
10
10
 
11
- export const A4UI_VERSION = '0.35.2'
11
+ export const A4UI_VERSION = '0.36.0'
12
12
 
13
13
  // Helpers (src/lib) — generic, framework-level utilities.
14
14
  export { cn } from './lib/cn'
@@ -31,6 +31,18 @@ export interface DataGridProps {
31
31
  pageSize?: number
32
32
  /** Show the global text filter above the table. Defaults to true. */
33
33
  filterable?: boolean
34
+ /**
35
+ * Copy overrides, for apps that do not run in English. Every user-visible
36
+ * string this component renders on its own is here; without them a Spanish
37
+ * or French page shows "Filter…" and "12 rows" in the middle of its own
38
+ * table with no way to change it.
39
+ * @default 'Filter…'
40
+ */
41
+ filterPlaceholder?: string
42
+ /** Accessible name for the filter box. @default 'Filter rows' */
43
+ filterLabel?: string
44
+ /** Builds the row-count summary. @default (n) => `${n} rows` */
45
+ rowsSummary?: (count: number) => string
34
46
  class?: string
35
47
  }
36
48
 
@@ -126,8 +138,8 @@ export function DataGrid(props: DataGridProps): JSX.Element {
126
138
  setQuery(v)
127
139
  setPage(1)
128
140
  }}
129
- placeholder="Filter…"
130
- aria-label="Filter rows"
141
+ placeholder={props.filterPlaceholder ?? 'Filter…'}
142
+ aria-label={props.filterLabel ?? 'Filter rows'}
131
143
  />
132
144
  </div>
133
145
  )}
@@ -170,7 +182,7 @@ export function DataGrid(props: DataGridProps): JSX.Element {
170
182
  page={Math.min(page(), totalPages())}
171
183
  totalPages={totalPages()}
172
184
  onChange={setPage}
173
- summary={`${sorted().length} rows`}
185
+ summary={props.rowsSummary?.(sorted().length) ?? `${sorted().length} rows`}
174
186
  />
175
187
  </div>
176
188
  )
@@ -20,6 +20,15 @@ export interface LocationPickerProps {
20
20
  value?: LocationValue
21
21
  /** Fires with the full value whenever the label, the pin, or geolocation changes it. */
22
22
  onChange?: (v: LocationValue) => void
23
+ /**
24
+ * Placeholder for the free-text label field. Overridable because this was
25
+ * hardcoded English inside an otherwise fully translatable component — a
26
+ * Spanish form showed "Location label" in the middle of its own wizard.
27
+ * @default 'Location label'
28
+ */
29
+ labelPlaceholder?: string
30
+ /** Accessible name for the "use my location" button. @default 'Use my location' */
31
+ geolocateLabel?: string
23
32
  class?: string
24
33
  }
25
34
 
@@ -77,10 +86,14 @@ export function LocationPicker(props: LocationPickerProps): JSX.Element {
77
86
  type="text"
78
87
  value={current().label ?? ''}
79
88
  onInput={(event) => setLabel(event.currentTarget.value)}
80
- placeholder="Location label"
89
+ placeholder={props.labelPlaceholder ?? 'Location label'}
81
90
  class="h-9 flex-1 rounded-md border border-border bg-input px-3 text-sm text-foreground placeholder:text-muted-foreground focus:ring-2 focus:ring-ring focus:outline-none"
82
91
  />
83
- <Button variant="outline" aria-label="Use my location" onClick={useMyLocation}>
92
+ <Button
93
+ variant="outline"
94
+ aria-label={props.geolocateLabel ?? 'Use my location'}
95
+ onClick={useMyLocation}
96
+ >
84
97
  <Crosshair class="h-4 w-4" />
85
98
  </Button>
86
99
  </div>
package/src/ui/Table.tsx CHANGED
@@ -34,7 +34,15 @@ interface TableProps extends ParentProps {
34
34
  export function Table(props: TableProps): JSX.Element {
35
35
  const [local, rest] = splitProps(props, ['class', 'children'])
36
36
  return (
37
- <div class="w-full overflow-x-auto">
37
+ // `relative` is load-bearing, not decoration: `overflow` only clips a
38
+ // descendant whose containing block is inside the scroller. Without a
39
+ // positioned wrapper, an absolutely-positioned descendant (a
40
+ // screen-reader-only input inside a cell control, for instance) resolves
41
+ // against an ancestor further up, escapes the clip at the table's full
42
+ // scroll width, and drags the whole DOCUMENT into horizontal scrolling —
43
+ // measured on a phone: a 356 px table inside a 390 px viewport pushed the
44
+ // page to 413 px.
45
+ <div class="relative w-full overflow-x-auto">
38
46
  <table class={cn('w-full border-collapse text-sm', local.class)} {...rest}>
39
47
  {local.children}
40
48
  </table>