@almadar/ui 5.122.14 → 5.123.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.
@@ -1848,6 +1848,7 @@ var init_Button = __esm({
1848
1848
  "button",
1849
1849
  {
1850
1850
  ref,
1851
+ type: "button",
1851
1852
  disabled: disabled || isLoading,
1852
1853
  className: cn(
1853
1854
  "relative inline-flex items-center justify-center gap-2",
@@ -4014,6 +4015,11 @@ var init_Typography = __esm({
4014
4015
  inherit: "text-inherit"
4015
4016
  };
4016
4017
  weightStyles = {
4018
+ // Neutral: an atom default of "none" must not override the variant's baked
4019
+ // weight (C-PATTERN-ENUM-BLOCKS-NEUTRAL-OVERRIDE — `variant={h2}` rendered
4020
+ // tiny because the ui-typography atom's `weight: light`/`size: xs` defaults
4021
+ // clobbered every variant).
4022
+ none: "",
4017
4023
  light: "font-light",
4018
4024
  normal: "font-normal",
4019
4025
  medium: "font-medium",
@@ -4039,6 +4045,7 @@ var init_Typography = __esm({
4039
4045
  label: "span"
4040
4046
  };
4041
4047
  typographySizeStyles = {
4048
+ none: "",
4042
4049
  xs: "text-xs",
4043
4050
  sm: "text-sm",
4044
4051
  md: "text-base",
@@ -20723,6 +20730,13 @@ function DataGrid({
20723
20730
  row: itemData
20724
20731
  };
20725
20732
  eventBus.emit(`UI:${action.event}`, payload);
20733
+ if (action.navigatesTo) {
20734
+ const url = action.navigatesTo.replace(
20735
+ /\{\{row\.(\w+(?:\.\w+)*)\}\}/g,
20736
+ (_, field) => String(itemData[field] ?? "")
20737
+ );
20738
+ eventBus.emit("UI:NAVIGATE", { url });
20739
+ }
20726
20740
  };
20727
20741
  const hasRenderProp = typeof children === "function";
20728
20742
  React74.useEffect(() => {
@@ -20790,13 +20804,49 @@ function DataGrid({
20790
20804
  const wrapDnd = (node) => dnd.isZone ? /* @__PURE__ */ jsxRuntime.jsx(dnd.SortableItem, { id: dndId, children: node }, dndId) : node;
20791
20805
  if (hasRenderProp) {
20792
20806
  return wrapDnd(
20793
- /* @__PURE__ */ jsxRuntime.jsx(
20807
+ /* @__PURE__ */ jsxRuntime.jsxs(
20794
20808
  exports.Box,
20795
20809
  {
20796
20810
  "data-entity-row": true,
20797
20811
  "data-entity-id": id,
20798
20812
  className: cn(isSelected && "ring-2 ring-primary rounded-lg"),
20799
- children: children(itemData, index)
20813
+ children: [
20814
+ children(itemData, index),
20815
+ actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "justify-end", children: [
20816
+ (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
20817
+ exports.Button,
20818
+ {
20819
+ variant: action.variant === "primary" ? "primary" : "ghost",
20820
+ size: "sm",
20821
+ onClick: handleActionClick(action, itemData),
20822
+ "data-testid": `action-${action.event}`,
20823
+ "data-row-id": String(itemData.id),
20824
+ className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
20825
+ children: [
20826
+ action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20827
+ action.label
20828
+ ]
20829
+ },
20830
+ idx
20831
+ )),
20832
+ maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
20833
+ exports.Menu,
20834
+ {
20835
+ position: "bottom-end",
20836
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "more-horizontal", size: "xs" }) }),
20837
+ items: actionDefs.slice(maxInlineActions).map((action) => ({
20838
+ label: action.label,
20839
+ icon: action.icon,
20840
+ event: action.event,
20841
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
20842
+ id: itemData.id,
20843
+ row: itemData
20844
+ })
20845
+ }))
20846
+ }
20847
+ )
20848
+ ] }) })
20849
+ ]
20800
20850
  },
20801
20851
  id
20802
20852
  )
@@ -22662,7 +22712,9 @@ var init_FilterGroup = __esm({
22662
22712
  showIcon = true,
22663
22713
  query,
22664
22714
  isLoading,
22665
- look = "toolbar"
22715
+ look = "toolbar",
22716
+ event,
22717
+ clearEvent
22666
22718
  }) => {
22667
22719
  const { t } = hooks.useTranslate();
22668
22720
  const eventBus = useEventBus();
@@ -22699,14 +22751,18 @@ var init_FilterGroup = __esm({
22699
22751
  queryState.setFilter(field, value === "all" ? null : value);
22700
22752
  }
22701
22753
  onFilterChange?.(field, value === "all" ? null : value);
22702
- eventBus.emit("UI:FILTER", {
22754
+ const payload = {
22703
22755
  entity,
22704
22756
  field,
22705
22757
  value: value === "all" || value === null ? "" : value,
22706
22758
  query
22707
- });
22759
+ };
22760
+ if (event && event !== "FILTER") {
22761
+ eventBus.emit(`UI:${event}`, payload);
22762
+ }
22763
+ eventBus.emit("UI:FILTER", payload);
22708
22764
  },
22709
- [onFilterChange, queryState, eventBus, entity, query]
22765
+ [onFilterChange, queryState, eventBus, entity, query, event]
22710
22766
  );
22711
22767
  const handleClearAll = React74.useCallback(() => {
22712
22768
  setSelectedValues({});
@@ -22714,8 +22770,11 @@ var init_FilterGroup = __esm({
22714
22770
  queryState.clearFilters();
22715
22771
  }
22716
22772
  onClearAll?.();
22773
+ if (clearEvent && clearEvent !== "CLEAR_FILTERS") {
22774
+ eventBus.emit(`UI:${clearEvent}`, { entity, query });
22775
+ }
22717
22776
  eventBus.emit("UI:CLEAR_FILTERS", { entity, query });
22718
- }, [onClearAll, queryState, eventBus, entity, query]);
22777
+ }, [onClearAll, queryState, eventBus, entity, query, clearEvent]);
22719
22778
  const activeFilterCount = Object.keys(selectedValues).length;
22720
22779
  if (variant === "pills") {
22721
22780
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -24093,7 +24152,7 @@ var init_SearchInput = __esm({
24093
24152
  queryState.setSearch(newValue);
24094
24153
  }
24095
24154
  onSearch?.(newValue);
24096
- if (event) {
24155
+ if (event && event !== "SEARCH") {
24097
24156
  eventBus.emit(`UI:${event}`, { searchTerm: newValue, entity });
24098
24157
  }
24099
24158
  if (event || entity || query) {
@@ -47311,6 +47370,14 @@ function useUISlotManager() {
47311
47370
  [sourceKey]: content
47312
47371
  };
47313
47372
  const nextAll = { ...prev, [config.target]: nextSources };
47373
+ const priorWriters = Object.keys(slotSources);
47374
+ if (priorWriters.length === 1 && priorWriters[0] !== sourceKey) {
47375
+ log17.warn("slot:contention", {
47376
+ slot: config.target,
47377
+ writers: [priorWriters[0], sourceKey],
47378
+ patternTypes: [slotSources[priorWriters[0]].pattern, content.pattern]
47379
+ });
47380
+ }
47314
47381
  if (content.sourceTrait) {
47315
47382
  indexTraitRender(content.sourceTrait, content);
47316
47383
  notifyTraitSubscribers(content.sourceTrait, content);
@@ -1104,7 +1104,8 @@ declare const TextHighlight: React__default.FC<TextHighlightProps>;
1104
1104
  */
1105
1105
 
1106
1106
  type TypographyVariant = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "heading" | "subheading" | "body1" | "body2" | "body" | "caption" | "overline" | "small" | "large" | "label";
1107
- type TypographySize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
1107
+ /** `none` = no size override the variant's baked size applies. */
1108
+ type TypographySize = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
1108
1109
  interface TypographyProps {
1109
1110
  /** Typography variant */
1110
1111
  variant?: TypographyVariant;
@@ -1114,8 +1115,8 @@ interface TypographyProps {
1114
1115
  color?: "primary" | "secondary" | "muted" | "error" | "success" | "warning" | "inherit";
1115
1116
  /** Text alignment */
1116
1117
  align?: "left" | "center" | "right";
1117
- /** Font weight override */
1118
- weight?: "light" | "normal" | "medium" | "semibold" | "bold";
1118
+ /** Font weight override — `none` = no override, the variant's baked weight applies */
1119
+ weight?: "none" | "light" | "normal" | "medium" | "semibold" | "bold";
1119
1120
  /** Font size override */
1120
1121
  size?: TypographySize;
1121
1122
  /** Truncate with ellipsis (single line) */
@@ -4005,6 +4006,10 @@ interface FilterGroupProps {
4005
4006
  isLoading?: boolean;
4006
4007
  /** Layer 2 visual treatment — orthogonal to the semantic variant. */
4007
4008
  look?: FilterGroupLook;
4009
+ /** Declarative filter event — emits UI:{event} via eventBus on filter change (alongside canonical UI:FILTER) */
4010
+ event?: EventKey;
4011
+ /** Declarative clear event — emits UI:{clearEvent} via eventBus on clear-all (alongside canonical UI:CLEAR_FILTERS) */
4012
+ clearEvent?: EventKey;
4008
4013
  }
4009
4014
  /**
4010
4015
  * FilterGroup - Renders filter controls for entity data
@@ -4683,11 +4688,8 @@ interface SearchInputProps extends Omit<React__default.InputHTMLAttributes<HTMLI
4683
4688
  * Additional CSS classes
4684
4689
  */
4685
4690
  className?: string;
4686
- /**
4687
- * Event name to dispatch on search (schema metadata, wired by trait)
4688
- * This is metadata used by the trait generator, not by the component.
4689
- */
4690
- event?: string;
4691
+ /** Declarative search event — emits UI:{event} via eventBus on query submit (alongside canonical UI:SEARCH) */
4692
+ event?: EventKey;
4691
4693
  /**
4692
4694
  * Entity type for context-aware search.
4693
4695
  * When provided, search events include entity context.
@@ -6323,6 +6325,9 @@ interface DataGridItemAction {
6323
6325
  label: string;
6324
6326
  /** Event name to emit (dispatched as UI:{event} with { row: itemData }) */
6325
6327
  event: EventKey;
6328
+ /** Route to navigate to instead of (or after) emitting — `{{row.field}}`
6329
+ * placeholders interpolate from the item row (CardGrid's contract). */
6330
+ navigatesTo?: string;
6326
6331
  /** Lucide icon name or component */
6327
6332
  icon?: IconInput;
6328
6333
  /** Button variant */
@@ -6379,8 +6384,8 @@ interface DataGridProps extends DataDndProps {
6379
6384
  loadMoreEvent?: EventKey;
6380
6385
  /** Whether more items are available for infinite scroll */
6381
6386
  hasMore?: boolean;
6382
- /** Render prop for custom per-card content. When provided, `fields` and
6383
- * `itemActions` are ignored. */
6387
+ /** Render prop for custom per-card content. When provided, `fields` are
6388
+ * ignored; `itemActions` render as a footer beneath the custom content. */
6384
6389
  children?: (item: EntityRow, index: number) => React__default.ReactNode;
6385
6390
  /**
6386
6391
  * Per-item render function (schema-level alias for children render prop).
@@ -1104,7 +1104,8 @@ declare const TextHighlight: React__default.FC<TextHighlightProps>;
1104
1104
  */
1105
1105
 
1106
1106
  type TypographyVariant = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "heading" | "subheading" | "body1" | "body2" | "body" | "caption" | "overline" | "small" | "large" | "label";
1107
- type TypographySize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
1107
+ /** `none` = no size override the variant's baked size applies. */
1108
+ type TypographySize = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
1108
1109
  interface TypographyProps {
1109
1110
  /** Typography variant */
1110
1111
  variant?: TypographyVariant;
@@ -1114,8 +1115,8 @@ interface TypographyProps {
1114
1115
  color?: "primary" | "secondary" | "muted" | "error" | "success" | "warning" | "inherit";
1115
1116
  /** Text alignment */
1116
1117
  align?: "left" | "center" | "right";
1117
- /** Font weight override */
1118
- weight?: "light" | "normal" | "medium" | "semibold" | "bold";
1118
+ /** Font weight override — `none` = no override, the variant's baked weight applies */
1119
+ weight?: "none" | "light" | "normal" | "medium" | "semibold" | "bold";
1119
1120
  /** Font size override */
1120
1121
  size?: TypographySize;
1121
1122
  /** Truncate with ellipsis (single line) */
@@ -4005,6 +4006,10 @@ interface FilterGroupProps {
4005
4006
  isLoading?: boolean;
4006
4007
  /** Layer 2 visual treatment — orthogonal to the semantic variant. */
4007
4008
  look?: FilterGroupLook;
4009
+ /** Declarative filter event — emits UI:{event} via eventBus on filter change (alongside canonical UI:FILTER) */
4010
+ event?: EventKey;
4011
+ /** Declarative clear event — emits UI:{clearEvent} via eventBus on clear-all (alongside canonical UI:CLEAR_FILTERS) */
4012
+ clearEvent?: EventKey;
4008
4013
  }
4009
4014
  /**
4010
4015
  * FilterGroup - Renders filter controls for entity data
@@ -4683,11 +4688,8 @@ interface SearchInputProps extends Omit<React__default.InputHTMLAttributes<HTMLI
4683
4688
  * Additional CSS classes
4684
4689
  */
4685
4690
  className?: string;
4686
- /**
4687
- * Event name to dispatch on search (schema metadata, wired by trait)
4688
- * This is metadata used by the trait generator, not by the component.
4689
- */
4690
- event?: string;
4691
+ /** Declarative search event — emits UI:{event} via eventBus on query submit (alongside canonical UI:SEARCH) */
4692
+ event?: EventKey;
4691
4693
  /**
4692
4694
  * Entity type for context-aware search.
4693
4695
  * When provided, search events include entity context.
@@ -6323,6 +6325,9 @@ interface DataGridItemAction {
6323
6325
  label: string;
6324
6326
  /** Event name to emit (dispatched as UI:{event} with { row: itemData }) */
6325
6327
  event: EventKey;
6328
+ /** Route to navigate to instead of (or after) emitting — `{{row.field}}`
6329
+ * placeholders interpolate from the item row (CardGrid's contract). */
6330
+ navigatesTo?: string;
6326
6331
  /** Lucide icon name or component */
6327
6332
  icon?: IconInput;
6328
6333
  /** Button variant */
@@ -6379,8 +6384,8 @@ interface DataGridProps extends DataDndProps {
6379
6384
  loadMoreEvent?: EventKey;
6380
6385
  /** Whether more items are available for infinite scroll */
6381
6386
  hasMore?: boolean;
6382
- /** Render prop for custom per-card content. When provided, `fields` and
6383
- * `itemActions` are ignored. */
6387
+ /** Render prop for custom per-card content. When provided, `fields` are
6388
+ * ignored; `itemActions` render as a footer beneath the custom content. */
6384
6389
  children?: (item: EntityRow, index: number) => React__default.ReactNode;
6385
6390
  /**
6386
6391
  * Per-item render function (schema-level alias for children render prop).
@@ -1773,6 +1773,7 @@ var init_Button = __esm({
1773
1773
  "button",
1774
1774
  {
1775
1775
  ref,
1776
+ type: "button",
1776
1777
  disabled: disabled || isLoading,
1777
1778
  className: cn(
1778
1779
  "relative inline-flex items-center justify-center gap-2",
@@ -3939,6 +3940,11 @@ var init_Typography = __esm({
3939
3940
  inherit: "text-inherit"
3940
3941
  };
3941
3942
  weightStyles = {
3943
+ // Neutral: an atom default of "none" must not override the variant's baked
3944
+ // weight (C-PATTERN-ENUM-BLOCKS-NEUTRAL-OVERRIDE — `variant={h2}` rendered
3945
+ // tiny because the ui-typography atom's `weight: light`/`size: xs` defaults
3946
+ // clobbered every variant).
3947
+ none: "",
3942
3948
  light: "font-light",
3943
3949
  normal: "font-normal",
3944
3950
  medium: "font-medium",
@@ -3964,6 +3970,7 @@ var init_Typography = __esm({
3964
3970
  label: "span"
3965
3971
  };
3966
3972
  typographySizeStyles = {
3973
+ none: "",
3967
3974
  xs: "text-xs",
3968
3975
  sm: "text-sm",
3969
3976
  md: "text-base",
@@ -20648,6 +20655,13 @@ function DataGrid({
20648
20655
  row: itemData
20649
20656
  };
20650
20657
  eventBus.emit(`UI:${action.event}`, payload);
20658
+ if (action.navigatesTo) {
20659
+ const url = action.navigatesTo.replace(
20660
+ /\{\{row\.(\w+(?:\.\w+)*)\}\}/g,
20661
+ (_, field) => String(itemData[field] ?? "")
20662
+ );
20663
+ eventBus.emit("UI:NAVIGATE", { url });
20664
+ }
20651
20665
  };
20652
20666
  const hasRenderProp = typeof children === "function";
20653
20667
  useEffect(() => {
@@ -20715,13 +20729,49 @@ function DataGrid({
20715
20729
  const wrapDnd = (node) => dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: dndId, children: node }, dndId) : node;
20716
20730
  if (hasRenderProp) {
20717
20731
  return wrapDnd(
20718
- /* @__PURE__ */ jsx(
20732
+ /* @__PURE__ */ jsxs(
20719
20733
  Box,
20720
20734
  {
20721
20735
  "data-entity-row": true,
20722
20736
  "data-entity-id": id,
20723
20737
  className: cn(isSelected && "ring-2 ring-primary rounded-lg"),
20724
- children: children(itemData, index)
20738
+ children: [
20739
+ children(itemData, index),
20740
+ actionDefs.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-end", children: [
20741
+ (maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : actionDefs).map((action, idx) => /* @__PURE__ */ jsxs(
20742
+ Button,
20743
+ {
20744
+ variant: action.variant === "primary" ? "primary" : "ghost",
20745
+ size: "sm",
20746
+ onClick: handleActionClick(action, itemData),
20747
+ "data-testid": `action-${action.event}`,
20748
+ "data-row-id": String(itemData.id),
20749
+ className: action.variant === "danger" ? "text-error hover:text-error hover:bg-error/10" : void 0,
20750
+ children: [
20751
+ action.icon && renderIconInput(action.icon, { size: "xs", className: "mr-1" }),
20752
+ action.label
20753
+ ]
20754
+ },
20755
+ idx
20756
+ )),
20757
+ maxInlineActions != null && actionDefs.length > maxInlineActions && /* @__PURE__ */ jsx(
20758
+ Menu,
20759
+ {
20760
+ position: "bottom-end",
20761
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
20762
+ items: actionDefs.slice(maxInlineActions).map((action) => ({
20763
+ label: action.label,
20764
+ icon: action.icon,
20765
+ event: action.event,
20766
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
20767
+ id: itemData.id,
20768
+ row: itemData
20769
+ })
20770
+ }))
20771
+ }
20772
+ )
20773
+ ] }) })
20774
+ ]
20725
20775
  },
20726
20776
  id
20727
20777
  )
@@ -22587,7 +22637,9 @@ var init_FilterGroup = __esm({
22587
22637
  showIcon = true,
22588
22638
  query,
22589
22639
  isLoading,
22590
- look = "toolbar"
22640
+ look = "toolbar",
22641
+ event,
22642
+ clearEvent
22591
22643
  }) => {
22592
22644
  const { t } = useTranslate();
22593
22645
  const eventBus = useEventBus();
@@ -22624,14 +22676,18 @@ var init_FilterGroup = __esm({
22624
22676
  queryState.setFilter(field, value === "all" ? null : value);
22625
22677
  }
22626
22678
  onFilterChange?.(field, value === "all" ? null : value);
22627
- eventBus.emit("UI:FILTER", {
22679
+ const payload = {
22628
22680
  entity,
22629
22681
  field,
22630
22682
  value: value === "all" || value === null ? "" : value,
22631
22683
  query
22632
- });
22684
+ };
22685
+ if (event && event !== "FILTER") {
22686
+ eventBus.emit(`UI:${event}`, payload);
22687
+ }
22688
+ eventBus.emit("UI:FILTER", payload);
22633
22689
  },
22634
- [onFilterChange, queryState, eventBus, entity, query]
22690
+ [onFilterChange, queryState, eventBus, entity, query, event]
22635
22691
  );
22636
22692
  const handleClearAll = useCallback(() => {
22637
22693
  setSelectedValues({});
@@ -22639,8 +22695,11 @@ var init_FilterGroup = __esm({
22639
22695
  queryState.clearFilters();
22640
22696
  }
22641
22697
  onClearAll?.();
22698
+ if (clearEvent && clearEvent !== "CLEAR_FILTERS") {
22699
+ eventBus.emit(`UI:${clearEvent}`, { entity, query });
22700
+ }
22642
22701
  eventBus.emit("UI:CLEAR_FILTERS", { entity, query });
22643
- }, [onClearAll, queryState, eventBus, entity, query]);
22702
+ }, [onClearAll, queryState, eventBus, entity, query, clearEvent]);
22644
22703
  const activeFilterCount = Object.keys(selectedValues).length;
22645
22704
  if (variant === "pills") {
22646
22705
  return /* @__PURE__ */ jsxs(
@@ -24018,7 +24077,7 @@ var init_SearchInput = __esm({
24018
24077
  queryState.setSearch(newValue);
24019
24078
  }
24020
24079
  onSearch?.(newValue);
24021
- if (event) {
24080
+ if (event && event !== "SEARCH") {
24022
24081
  eventBus.emit(`UI:${event}`, { searchTerm: newValue, entity });
24023
24082
  }
24024
24083
  if (event || entity || query) {
@@ -47236,6 +47295,14 @@ function useUISlotManager() {
47236
47295
  [sourceKey]: content
47237
47296
  };
47238
47297
  const nextAll = { ...prev, [config.target]: nextSources };
47298
+ const priorWriters = Object.keys(slotSources);
47299
+ if (priorWriters.length === 1 && priorWriters[0] !== sourceKey) {
47300
+ log17.warn("slot:contention", {
47301
+ slot: config.target,
47302
+ writers: [priorWriters[0], sourceKey],
47303
+ patternTypes: [slotSources[priorWriters[0]].pattern, content.pattern]
47304
+ });
47305
+ }
47239
47306
  if (content.sourceTrait) {
47240
47307
  indexTraitRender(content.sourceTrait, content);
47241
47308
  notifyTraitSubscribers(content.sourceTrait, content);
@@ -164,6 +164,14 @@ function useUISlotManager() {
164
164
  [sourceKey]: content
165
165
  };
166
166
  const nextAll = { ...prev, [config.target]: nextSources };
167
+ const priorWriters = Object.keys(slotSources);
168
+ if (priorWriters.length === 1 && priorWriters[0] !== sourceKey) {
169
+ log.warn("slot:contention", {
170
+ slot: config.target,
171
+ writers: [priorWriters[0], sourceKey],
172
+ patternTypes: [slotSources[priorWriters[0]].pattern, content.pattern]
173
+ });
174
+ }
167
175
  if (content.sourceTrait) {
168
176
  indexTraitRender(content.sourceTrait, content);
169
177
  notifyTraitSubscribers(content.sourceTrait, content);
@@ -622,6 +630,7 @@ var ThemeProvider = ({
622
630
  }
623
631
  const root = document.documentElement;
624
632
  root.setAttribute("data-theme", appliedTheme);
633
+ root.style.colorScheme = resolvedMode;
625
634
  root.classList.remove("light", "dark");
626
635
  root.classList.add(resolvedMode);
627
636
  }, [appliedTheme, resolvedMode, targetRef, isScoped]);
@@ -162,6 +162,14 @@ function useUISlotManager() {
162
162
  [sourceKey]: content
163
163
  };
164
164
  const nextAll = { ...prev, [config.target]: nextSources };
165
+ const priorWriters = Object.keys(slotSources);
166
+ if (priorWriters.length === 1 && priorWriters[0] !== sourceKey) {
167
+ log.warn("slot:contention", {
168
+ slot: config.target,
169
+ writers: [priorWriters[0], sourceKey],
170
+ patternTypes: [slotSources[priorWriters[0]].pattern, content.pattern]
171
+ });
172
+ }
165
173
  if (content.sourceTrait) {
166
174
  indexTraitRender(content.sourceTrait, content);
167
175
  notifyTraitSubscribers(content.sourceTrait, content);
@@ -620,6 +628,7 @@ var ThemeProvider = ({
620
628
  }
621
629
  const root = document.documentElement;
622
630
  root.setAttribute("data-theme", appliedTheme);
631
+ root.style.colorScheme = resolvedMode;
623
632
  root.classList.remove("light", "dark");
624
633
  root.classList.add(resolvedMode);
625
634
  }, [appliedTheme, resolvedMode, targetRef, isScoped]);
@@ -1177,6 +1177,14 @@ function useUISlotManager() {
1177
1177
  [sourceKey]: content
1178
1178
  };
1179
1179
  const nextAll = { ...prev, [config.target]: nextSources };
1180
+ const priorWriters = Object.keys(slotSources);
1181
+ if (priorWriters.length === 1 && priorWriters[0] !== sourceKey) {
1182
+ log11.warn("slot:contention", {
1183
+ slot: config.target,
1184
+ writers: [priorWriters[0], sourceKey],
1185
+ patternTypes: [slotSources[priorWriters[0]].pattern, content.pattern]
1186
+ });
1187
+ }
1180
1188
  if (content.sourceTrait) {
1181
1189
  indexTraitRender(content.sourceTrait, content);
1182
1190
  notifyTraitSubscribers(content.sourceTrait, content);
@@ -1175,6 +1175,14 @@ function useUISlotManager() {
1175
1175
  [sourceKey]: content
1176
1176
  };
1177
1177
  const nextAll = { ...prev, [config.target]: nextSources };
1178
+ const priorWriters = Object.keys(slotSources);
1179
+ if (priorWriters.length === 1 && priorWriters[0] !== sourceKey) {
1180
+ log11.warn("slot:contention", {
1181
+ slot: config.target,
1182
+ writers: [priorWriters[0], sourceKey],
1183
+ patternTypes: [slotSources[priorWriters[0]].pattern, content.pattern]
1184
+ });
1185
+ }
1178
1186
  if (content.sourceTrait) {
1179
1187
  indexTraitRender(content.sourceTrait, content);
1180
1188
  notifyTraitSubscribers(content.sourceTrait, content);
@@ -2823,6 +2823,11 @@ var colorStyles = {
2823
2823
  inherit: "text-inherit"
2824
2824
  };
2825
2825
  var weightStyles = {
2826
+ // Neutral: an atom default of "none" must not override the variant's baked
2827
+ // weight (C-PATTERN-ENUM-BLOCKS-NEUTRAL-OVERRIDE — `variant={h2}` rendered
2828
+ // tiny because the ui-typography atom's `weight: light`/`size: xs` defaults
2829
+ // clobbered every variant).
2830
+ none: "",
2826
2831
  light: "font-light",
2827
2832
  normal: "font-normal",
2828
2833
  medium: "font-medium",
@@ -2848,6 +2853,7 @@ var defaultElements = {
2848
2853
  label: "span"
2849
2854
  };
2850
2855
  var typographySizeStyles = {
2856
+ none: "",
2851
2857
  xs: "text-xs",
2852
2858
  sm: "text-sm",
2853
2859
  md: "text-base",
@@ -2799,6 +2799,11 @@ var colorStyles = {
2799
2799
  inherit: "text-inherit"
2800
2800
  };
2801
2801
  var weightStyles = {
2802
+ // Neutral: an atom default of "none" must not override the variant's baked
2803
+ // weight (C-PATTERN-ENUM-BLOCKS-NEUTRAL-OVERRIDE — `variant={h2}` rendered
2804
+ // tiny because the ui-typography atom's `weight: light`/`size: xs` defaults
2805
+ // clobbered every variant).
2806
+ none: "",
2802
2807
  light: "font-light",
2803
2808
  normal: "font-normal",
2804
2809
  medium: "font-medium",
@@ -2824,6 +2829,7 @@ var defaultElements = {
2824
2829
  label: "span"
2825
2830
  };
2826
2831
  var typographySizeStyles = {
2832
+ none: "",
2827
2833
  xs: "text-xs",
2828
2834
  sm: "text-sm",
2829
2835
  md: "text-base",
@@ -2986,6 +2986,11 @@ var colorStyles = {
2986
2986
  inherit: "text-inherit"
2987
2987
  };
2988
2988
  var weightStyles = {
2989
+ // Neutral: an atom default of "none" must not override the variant's baked
2990
+ // weight (C-PATTERN-ENUM-BLOCKS-NEUTRAL-OVERRIDE — `variant={h2}` rendered
2991
+ // tiny because the ui-typography atom's `weight: light`/`size: xs` defaults
2992
+ // clobbered every variant).
2993
+ none: "",
2989
2994
  light: "font-light",
2990
2995
  normal: "font-normal",
2991
2996
  medium: "font-medium",
@@ -3011,6 +3016,7 @@ var defaultElements = {
3011
3016
  label: "span"
3012
3017
  };
3013
3018
  var typographySizeStyles = {
3019
+ none: "",
3014
3020
  xs: "text-xs",
3015
3021
  sm: "text-sm",
3016
3022
  md: "text-base",
@@ -3533,6 +3539,7 @@ var Button = React12__namespace.default.forwardRef(
3533
3539
  "button",
3534
3540
  {
3535
3541
  ref,
3542
+ type: "button",
3536
3543
  disabled: disabled || isLoading,
3537
3544
  className: cn(
3538
3545
  "relative inline-flex items-center justify-center gap-2",
@@ -2965,6 +2965,11 @@ var colorStyles = {
2965
2965
  inherit: "text-inherit"
2966
2966
  };
2967
2967
  var weightStyles = {
2968
+ // Neutral: an atom default of "none" must not override the variant's baked
2969
+ // weight (C-PATTERN-ENUM-BLOCKS-NEUTRAL-OVERRIDE — `variant={h2}` rendered
2970
+ // tiny because the ui-typography atom's `weight: light`/`size: xs` defaults
2971
+ // clobbered every variant).
2972
+ none: "",
2968
2973
  light: "font-light",
2969
2974
  normal: "font-normal",
2970
2975
  medium: "font-medium",
@@ -2990,6 +2995,7 @@ var defaultElements = {
2990
2995
  label: "span"
2991
2996
  };
2992
2997
  var typographySizeStyles = {
2998
+ none: "",
2993
2999
  xs: "text-xs",
2994
3000
  sm: "text-sm",
2995
3001
  md: "text-base",
@@ -3512,6 +3518,7 @@ var Button = React12__default.forwardRef(
3512
3518
  "button",
3513
3519
  {
3514
3520
  ref,
3521
+ type: "button",
3515
3522
  disabled: disabled || isLoading,
3516
3523
  className: cn(
3517
3524
  "relative inline-flex items-center justify-center gap-2",