@godxjp/ui 18.0.0 → 18.0.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.
@@ -428,7 +428,7 @@ DataTable.Content = function DataTableContent() {
428
428
  className: "ui-data-table-surface min-w-[640px] sm:min-w-0",
429
429
  "data-striped": striped ? "" : void 0,
430
430
  "data-hoverable": hoverable ? "" : void 0,
431
- children: /* @__PURE__ */ jsxs(Table, { children: [
431
+ children: /* @__PURE__ */ jsxs(Table, { scrollable: false, children: [
432
432
  /* @__PURE__ */ jsx(TableHeader, { className: cn("bg-secondary", stickyHeader && "sticky top-0 z-10"), children: /* @__PURE__ */ jsxs(TableRow, { children: [
433
433
  selectable && /* @__PURE__ */ jsx(TableHead, { className: "w-10", children: /* @__PURE__ */ jsx(DataTable.SelectAll, {}) }),
434
434
  visibleColumns.map((col) => {
@@ -1,5 +1,24 @@
1
1
  import * as React from "react";
2
- export declare const Table: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableElement> & React.RefAttributes<HTMLTableElement>>;
2
+ export type TableProps = React.HTMLAttributes<HTMLTableElement> & {
3
+ /**
4
+ * Whether the Table owns its own horizontal-scroll region (default `true`). When `true` a
5
+ * table wider than its container scrolls inside a keyboard-reachable wrapper (WCAG 2.1.1 / axe
6
+ * `scrollable-region-focusable`). Set `false` when an ancestor already provides the scroll
7
+ * region (e.g. `DataTable`, whose `.ui-data-table-scroll` owns the overflow + tab stop) — this
8
+ * avoids a redundant NESTED scroll container and a duplicate keyboard focus stop for one table.
9
+ */
10
+ scrollable?: boolean;
11
+ };
12
+ export declare const Table: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableElement> & {
13
+ /**
14
+ * Whether the Table owns its own horizontal-scroll region (default `true`). When `true` a
15
+ * table wider than its container scrolls inside a keyboard-reachable wrapper (WCAG 2.1.1 / axe
16
+ * `scrollable-region-focusable`). Set `false` when an ancestor already provides the scroll
17
+ * region (e.g. `DataTable`, whose `.ui-data-table-scroll` owns the overflow + tab stop) — this
18
+ * avoids a redundant NESTED scroll container and a duplicate keyboard focus stop for one table.
19
+ */
20
+ scrollable?: boolean;
21
+ } & React.RefAttributes<HTMLTableElement>>;
3
22
  export declare const TableHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
4
23
  export declare const TableBody: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
5
24
  export declare const TableRow: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableRowElement> & React.RefAttributes<HTMLTableRowElement>>;
@@ -3,19 +3,28 @@ import * as React from "react";
3
3
  import { tableHeadHeightClass } from "../../lib/control-styles.js";
4
4
  import { cn } from "../../lib/utils.js";
5
5
  const Table = React.forwardRef(
6
- ({ className, ...props }, ref) => (
6
+ ({ className, scrollable = true, ...props }, ref) => (
7
7
  // A table wider than its container scrolls horizontally in this wrapper; keep it
8
8
  // keyboard-reachable so it can be scrolled without a pointer (WCAG 2.1.1 / axe
9
9
  // scrollable-region-focusable). No landmark role — avoids landmark-unique collisions.
10
- /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", tabIndex: 0, children: /* @__PURE__ */ jsx(
11
- "table",
10
+ // When `scrollable` is false an ancestor owns the scroll region, so this is a bare
11
+ // positioning box (no `overflow`, no tab stop) to avoid a redundant nested scroller.
12
+ /* @__PURE__ */ jsx(
13
+ "div",
12
14
  {
13
- ref,
14
- "data-slot": "table",
15
- className: cn("w-full caption-bottom text-sm", className),
16
- ...props
15
+ className: scrollable ? "relative w-full overflow-auto" : "relative w-full",
16
+ ...scrollable ? { tabIndex: 0 } : {},
17
+ children: /* @__PURE__ */ jsx(
18
+ "table",
19
+ {
20
+ ref,
21
+ "data-slot": "table",
22
+ className: cn("w-full caption-bottom text-sm", className),
23
+ ...props
24
+ }
25
+ )
17
26
  }
18
- ) })
27
+ )
19
28
  )
20
29
  );
21
30
  Table.displayName = "Table";
@@ -63,7 +63,8 @@ const ARIA_KEY = {
63
63
  };
64
64
  const BRAND_NONE = "__app__";
65
65
  const AppSettingPicker = React.forwardRef(
66
- function AppSettingPicker2({ kind, appearance = "labeled", className, disabled, id, name, value, onValueChange }, ref) {
66
+ function AppSettingPicker2({ kind, appearance, className, disabled, id, name, value, onValueChange }, ref) {
67
+ const resolvedAppearance = appearance ?? (kind === "locale" ? "icon" : "labeled");
67
68
  const ctx = useOptionalAppContext();
68
69
  const { t, locale, fallbackLocale } = useTranslation();
69
70
  const raw = value ?? ctx?.[kind];
@@ -119,7 +120,7 @@ const AppSettingPicker = React.forwardRef(
119
120
  }, [kind, ctx?.timezoneOptions, current, t, locale, fallbackLocale]);
120
121
  const unbound = current === void 0 || !handleChange;
121
122
  const Icon = ICON[kind];
122
- const iconOnly = appearance === "icon";
123
+ const iconOnly = resolvedAppearance === "icon";
123
124
  return /* @__PURE__ */ jsxs(
124
125
  Select,
125
126
  {
@@ -134,12 +135,12 @@ const AppSettingPicker = React.forwardRef(
134
135
  {
135
136
  ref,
136
137
  id,
138
+ showIndicator: !iconOnly,
137
139
  className: cn(
138
140
  iconOnly ? (
139
- // Structurally icon-only: drop the owned width + value spacing, square the box to
140
- // the density-aware --control-height tap target, centre the icon and hide the
141
- // trailing chevron — no consumer descendant-selector overrides required.
142
- "w-[length:var(--control-height)] justify-center ps-0 pe-0 [&_[data-slot=select-chevron]]:hidden"
141
+ // Structurally icon-only: drop the owned width + value spacing and square the box to
142
+ // the density-aware --control-height tap target, centring the icon.
143
+ "w-[length:var(--control-height)] justify-center ps-0 pe-0"
143
144
  ) : (
144
145
  // Labeled: sized to a per-kind width from `sm` up; below `sm` it hugs its content and
145
146
  // caps at the container (`w-auto max-w-full`) instead of the old UNCONDITIONAL
@@ -43,6 +43,7 @@ const TagInput = React.forwardRef(
43
43
  "div",
44
44
  {
45
45
  "data-slot": "tag-input",
46
+ "aria-disabled": disabled || void 0,
46
47
  className: cn("ui-tag-input", disabled && "ui-tag-input-disabled", className),
47
48
  children: [
48
49
  tags.length > 0 ? /* @__PURE__ */ jsx("ul", { role: "list", className: "ui-tag-input-list", "data-slot": "tag-input-list", children: tags.map((tag, i) => /* @__PURE__ */ jsxs(
@@ -69,11 +69,15 @@ export type AppSettingKind = "locale" | "timezone" | "dateFormat" | "timeFormat"
69
69
  export type AppSettingPickerProp = {
70
70
  kind: AppSettingKind;
71
71
  /**
72
- * Trigger presentation. `"labeled"` (default) shows the leading icon + the selected value in a
73
- * full-width control. `"icon"` renders a supported square, icon-only topbar trigger (e.g. a globe
74
- * language switcher): it structurally drops the value text and the picker's owned width — no
75
- * descendant-selector CSS overrides needed — while always keeping the localized `aria-label`, so
76
- * an icon-only trigger can never ship without an accessible name.
72
+ * Trigger presentation. `"labeled"` shows the leading icon + the selected value in a control
73
+ * sized to the setting. `"icon"` renders a supported square, icon-only topbar trigger (e.g. a
74
+ * globe language switcher): it structurally drops the value text and the picker's owned width —
75
+ * no descendant-selector CSS overrides needed — while always keeping the localized `aria-label`,
76
+ * so an icon-only trigger can never ship without an accessible name.
77
+ *
78
+ * Default is kind-dependent: `kind="locale"` defaults to `"icon"` (its product contract is the
79
+ * compact language switcher); every other kind defaults to `"labeled"`. Override explicitly for
80
+ * e.g. a labeled locale row inside a settings form (`appearance="labeled"`).
77
81
  */
78
82
  appearance?: AppSettingPickerAppearanceProp;
79
83
  className?: ClassNameProp;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "18.0.0",
4
- "godxUiMcp": "17.0.1",
3
+ "version": "18.0.1",
4
+ "godxUiMcp": "18.0.0",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.29.1",
7
7
  "sideEffects": false,