@hjmds/react 0.9.4 → 0.9.6

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/styles.css CHANGED
@@ -14,6 +14,18 @@
14
14
  color: var(--hjm-color-text);
15
15
  }
16
16
 
17
+ /* host="contents": the element only carries the theme variables, dir and data
18
+ attributes. Custom properties still inherit through display: contents, so
19
+ recipes keep resolving; the product's own root paints the surface. */
20
+ .hjm-root[data-host="contents"] {
21
+ display: contents;
22
+ background: transparent;
23
+ color: inherit;
24
+ font-family: inherit;
25
+ font-size: inherit;
26
+ line-height: inherit;
27
+ }
28
+
17
29
  .hjm-visually-hidden {
18
30
  position: absolute !important;
19
31
  inline-size: 1px !important;
@@ -56,8 +68,12 @@
56
68
  border-radius: var(--hjm-radius-lg);
57
69
  background: var(--hjm-color-surface);
58
70
  }
71
+ /* A child image would otherwise spill past the rounded corner. An elevated tone
72
+ opts out because clipping cuts off its own shadow. */
73
+ .hjm-surface[data-clips="true"] { overflow: hidden; }
59
74
  .hjm-surface[data-tone="raised"] { background: var(--hjm-color-bg); box-shadow: 0 4px 12px rgb(0 0 0 / 12%); }
60
75
  .hjm-surface[data-tone="accent"] { background: var(--hjm-color-surface-accent); }
76
+ .hjm-surface[data-tone="sunken"] { background: var(--hjm-color-surface-alt); }
61
77
  .hjm-surface[data-tone="subtle"] { background: var(--hjm-color-bg); }
62
78
  .hjm-surface[data-bordered="true"] { border-color: var(--hjm-color-border); }
63
79
  .hjm-surface[data-tone="accent"][data-bordered="true"] { border-color: color-mix(in srgb, var(--hjm-color-primary) 30%, transparent); }
@@ -198,6 +214,11 @@
198
214
  position: absolute;
199
215
  inset: calc(-1 * var(--hjm-space-xxs));
200
216
  }
217
+ /* Shape and label alignment are recipe axes; a product must not override
218
+ border-radius or justify-content on the control itself. */
219
+ .hjm-button[data-shape="pill"] { border-radius: var(--hjm-radius-full); }
220
+ .hjm-button[data-align="leading"] { justify-content: flex-start; text-align: start; }
221
+
201
222
  .hjm-button[data-size="large"] {
202
223
  min-block-size: var(--hjm-control-button-large);
203
224
  padding-inline: var(--hjm-space-lg);
@@ -205,10 +226,15 @@
205
226
  line-height: var(--hjm-type-body-large-line-height);
206
227
  }
207
228
  .hjm-button[data-tone="primary"], .hjm-icon-button[data-tone="primary"] { color: var(--hjm-color-on-primary); background: var(--hjm-color-primary); }
208
- .hjm-button[data-tone="secondary"], .hjm-icon-button[data-tone="secondary"] { color: var(--hjm-color-text); background: var(--hjm-color-surface-alt); border-color: var(--hjm-color-text-sub); }
229
+ .hjm-button[data-tone="secondary"], .hjm-icon-button[data-tone="secondary"] { color: var(--hjm-color-text); background: var(--hjm-color-surface-alt); border-color: var(--hjm-color-border-control); }
209
230
  .hjm-button[data-tone="ghost"], .hjm-icon-button[data-tone="ghost"] { color: var(--hjm-color-text-muted); background: transparent; }
210
231
  .hjm-button[data-tone="danger"], .hjm-icon-button[data-tone="danger"] { color: var(--hjm-color-on-danger); background: var(--hjm-color-danger-fill); }
211
- .hjm-button[data-tone="link"] { color: var(--hjm-color-content-brand); background: transparent; }
232
+ /* A link-tone control is inline copy; the size axis' padding would push it out
233
+ of alignment with the text around it. */
234
+ .hjm-button[data-tone="link"] { color: var(--hjm-color-content-brand); background: transparent; padding-inline: 0; }
235
+ /* Toggle treatment: aria-pressed already carried the state, so without a paired
236
+ visual every consumer painted the selected background in product styles. */
237
+ .hjm-button[data-selected="true"] { color: var(--hjm-color-content-brand); background: var(--hjm-color-surface-accent); border-color: var(--hjm-color-content-brand); }
212
238
  .hjm-button:active:not(:disabled):not([aria-disabled="true"]), .hjm-icon-button:active:not(:disabled):not([aria-disabled="true"]) { transform: scale(0.98); }
213
239
  .hjm-button:disabled, .hjm-icon-button:disabled { cursor: not-allowed; opacity: 0.5; }
214
240
  .hjm-button__label { min-inline-size: 0; overflow-wrap: anywhere; }
@@ -281,8 +307,22 @@
281
307
  font: inherit;
282
308
  }
283
309
  .hjm-field__input::placeholder { color: var(--hjm-color-text-muted); opacity: 1; }
284
- .hjm-field__control--multiline { min-block-size: 80px; align-items: stretch; }
285
- .hjm-field__control--multiline textarea { min-block-size: 78px; resize: vertical; }
310
+ /* A short, ceremonial value (nickname, code) centres; the default follows the
311
+ resolved direction. Product code must not reach for `text-align`. */
312
+ .hjm-field[data-align="center"] .hjm-field__input { text-align: center; }
313
+ /* The multiline minimum came from the recipe, not from a hardcoded 80px, and a
314
+ consumer can widen or cap it in visible lines rather than pixels. */
315
+ .hjm-field__control--multiline { min-block-size: var(--hjm-field-multiline-min-height); align-items: stretch; }
316
+ .hjm-field__control--multiline textarea {
317
+ min-block-size: max(
318
+ calc(var(--hjm-field-multiline-min-height) - 2px),
319
+ calc(var(--hjm-field-min-visible-lines, 0) * var(--hjm-type-body-line-height) + var(--hjm-field-padding-block) * 2)
320
+ );
321
+ max-block-size: calc(
322
+ var(--hjm-field-max-visible-lines, 1000) * var(--hjm-type-body-line-height) + var(--hjm-field-padding-block) * 2
323
+ );
324
+ resize: vertical;
325
+ }
286
326
  .hjm-field__affix { display: inline-flex; align-items: center; color: var(--hjm-color-text-muted); }
287
327
  .hjm-field__description, .hjm-choice__description { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); }
288
328
  .hjm-field__error { color: var(--hjm-color-danger); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); }
@@ -690,11 +730,16 @@
690
730
 
691
731
  .hjm-switch { display: inline-flex; align-items: center; gap: var(--hjm-space-sm); min-block-size: var(--hjm-control-min-touch-target); padding: 0; border: 0; color: inherit; background: transparent; font: inherit; cursor: pointer; }
692
732
  .hjm-switch:disabled { opacity: 0.5; cursor: not-allowed; }
693
- .hjm-switch__track { display: flex; align-items: center; inline-size: 48px; block-size: 28px; padding: 3px; border-radius: var(--hjm-radius-full); background: var(--hjm-color-surface-alt); transition: background var(--hjm-motion-fast); }
694
- .hjm-switch__thumb { inline-size: 22px; block-size: 22px; border-radius: 50%; background: var(--hjm-color-bg); box-shadow: 0 1px 3px rgb(0 0 0 / 20%); transition: transform var(--hjm-motion-fast); }
733
+ /* Track and thumb geometry reads `switchRecipe.sizes`. The stylesheet used to
734
+ carry 48/28/22/3px, which matched neither recipe size, so the size axis was
735
+ unbound on web and consumers re-implemented it with their own variables. */
736
+ .hjm-switch { --hjm-switch-track-width: var(--hjm-switch-medium-width); --hjm-switch-track-height: var(--hjm-switch-medium-height); --hjm-switch-track-thumb: var(--hjm-switch-medium-thumb); --hjm-switch-track-inset: var(--hjm-switch-medium-inset); --hjm-switch-track-offset: var(--hjm-switch-medium-offset); }
737
+ .hjm-switch[data-size="small"] { --hjm-switch-track-width: var(--hjm-switch-small-width); --hjm-switch-track-height: var(--hjm-switch-small-height); --hjm-switch-track-thumb: var(--hjm-switch-small-thumb); --hjm-switch-track-inset: var(--hjm-switch-small-inset); --hjm-switch-track-offset: var(--hjm-switch-small-offset); }
738
+ .hjm-switch__track { display: flex; align-items: center; flex: 0 0 auto; inline-size: var(--hjm-switch-track-width); block-size: var(--hjm-switch-track-height); padding: var(--hjm-switch-track-inset); border-radius: var(--hjm-radius-full); background: var(--hjm-color-surface-alt); transition: background var(--hjm-motion-fast); }
739
+ .hjm-switch__thumb { inline-size: var(--hjm-switch-track-thumb); block-size: var(--hjm-switch-track-thumb); border-radius: 50%; background: var(--hjm-color-bg); box-shadow: 0 1px 3px rgb(0 0 0 / 20%); transition: transform var(--hjm-motion-fast); }
695
740
  .hjm-switch[data-state="checked"] .hjm-switch__track { background: var(--hjm-color-primary); }
696
- .hjm-switch[data-state="checked"] .hjm-switch__thumb { transform: translateX(20px); }
697
- [dir="rtl"] .hjm-switch[data-state="checked"] .hjm-switch__thumb { transform: translateX(-20px); }
741
+ .hjm-switch[data-state="checked"] .hjm-switch__thumb { transform: translateX(var(--hjm-switch-track-offset)); }
742
+ [dir="rtl"] .hjm-switch[data-state="checked"] .hjm-switch__thumb { transform: translateX(calc(-1 * var(--hjm-switch-track-offset))); }
698
743
 
699
744
  .hjm-segmented { min-inline-size: 0; padding: 0; border: 0; }
700
745
  .hjm-segmented__items { display: flex; min-inline-size: 0; gap: 2px; padding: 2px; border-radius: var(--hjm-radius-md); background: var(--hjm-color-surface-alt); overflow-x: auto; }
@@ -768,12 +813,20 @@
768
813
  .hjm-card__title { margin: 0; color: var(--hjm-color-text); font-size: var(--hjm-type-title-size); line-height: var(--hjm-type-title-line-height); overflow-wrap: anywhere; }
769
814
  .hjm-card__description { margin: 0; overflow-wrap: anywhere; }
770
815
  .hjm-card__actions { display: flex; flex-wrap: wrap; gap: var(--hjm-space-sm); padding: 0 var(--hjm-space-md) var(--hjm-space-md); }
771
- .hjm-list-row { inline-size: 100%; display: flex; align-items: center; gap: var(--hjm-space-sm); min-block-size: 56px; padding: var(--hjm-space-xs); border: 0; color: inherit; background: transparent; text-align: start; text-decoration: none; font: inherit; }
816
+ /* Row rhythm reads the recipe density variables so the stylesheet does not
817
+ carry a second copy of the same numbers. */
818
+ .hjm-list-row { inline-size: 100%; display: flex; align-items: center; gap: var(--hjm-list-row-gap); min-block-size: var(--hjm-list-row-comfortable-one-line); padding-inline: var(--hjm-list-row-comfortable-padding-inline); padding-block: var(--hjm-list-row-comfortable-padding-block); border: 0; color: inherit; background: transparent; text-align: start; text-decoration: none; font: inherit; }
772
819
  button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
773
- .hjm-list-row[data-density="compact"] { min-block-size: var(--hjm-control-min-touch-target); padding-block: var(--hjm-space-xxs); }
820
+ .hjm-list-row[data-lines="two"] { min-block-size: var(--hjm-list-row-comfortable-two-line); }
821
+ .hjm-list-row[data-density="compact"] { min-block-size: var(--hjm-list-row-compact-one-line); padding-inline: var(--hjm-list-row-compact-padding-inline); padding-block: var(--hjm-list-row-compact-padding-block); }
822
+ .hjm-list-row[data-density="compact"][data-lines="two"] { min-block-size: var(--hjm-list-row-compact-two-line); }
774
823
  .hjm-list-row[data-state="selected"] { background: var(--hjm-color-surface-accent); }
775
824
  .hjm-list-row[data-state="disabled"] { opacity: 0.5; cursor: not-allowed; }
776
825
  .hjm-list-row__leading, .hjm-list-row__trailing { flex: 0 0 auto; }
826
+ /* `leadingSize` was declared by the recipe but unbound, so consumers rebuilt
827
+ the avatar box in product styles. */
828
+ .hjm-list-row__leading { display: flex; align-items: center; justify-content: center; inline-size: var(--hjm-list-row-leading-size); block-size: var(--hjm-list-row-leading-size); overflow: hidden; }
829
+ .hjm-list-row__leading[data-shape="circle"] { border-radius: var(--hjm-radius-full); }
777
830
  .hjm-list-row__content { flex: 1 1 auto; min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); }
778
831
  .hjm-list-row__title { color: var(--hjm-color-text-body); font-weight: var(--hjm-font-weight-bold); overflow-wrap: anywhere; }
779
832
  .hjm-list-row__description, .hjm-list-row__trailing { color: var(--hjm-color-text-muted); overflow-wrap: anywhere; }
package/dist/theme.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DesignSystemProviderValue } from "@hjmds/design-contracts/components/design-system-provider";
1
+ import { type DesignSystemProviderValue } from "@hjmds/design-contracts/components/design-system-provider";
2
2
  import type { CSSProperties } from "react";
3
3
  export type HjmThemeStyle = CSSProperties & Record<`--hjm-${string}`, string | number>;
4
4
  export declare function createHjmThemeStyle(value: DesignSystemProviderValue): HjmThemeStyle;
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2DAA2D,CAAC;AAC3G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG,aAAa,GACvC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAU7C,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,yBAAyB,GAC/B,aAAa,CAiDf"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,2DAA2D,CAAC;AAGnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG,aAAa,GACvC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAU7C,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,yBAAyB,GAC/B,aAAa,CAyEf"}
package/dist/theme.js CHANGED
@@ -1,4 +1,7 @@
1
1
  import { control, fontFamily, fontWeight, motion, radius, spacing, typography, } from "@hjmds/design-contracts/foundations";
2
+ import { visibleControlHeight, } from "@hjmds/design-contracts/components/design-system-provider";
3
+ import { fieldRecipe } from "@hjmds/design-contracts/recipes/base";
4
+ import { listRowRecipe, switchRecipe } from "@hjmds/design-contracts/recipes";
2
5
  function kebab(value) {
3
6
  return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
4
7
  }
@@ -45,10 +48,32 @@ export function createHjmThemeStyle(value) {
45
48
  : `${value}ms`;
46
49
  }
47
50
  style["--hjm-font-family-ui"] = fontFamily.ui.join(", ");
51
+ // Row rhythm and the leading frame come from the recipe so the stylesheet
52
+ // does not carry a second copy of the same numbers.
53
+ style["--hjm-list-row-gap"] = rem(listRowRecipe.gap);
54
+ style["--hjm-list-row-leading-size"] = rem(listRowRecipe.leadingSize);
55
+ for (const [name, value] of Object.entries(switchRecipe.sizes)) {
56
+ style[`--hjm-switch-${kebab(name)}-width`] = rem(value.width);
57
+ style[`--hjm-switch-${kebab(name)}-height`] = rem(value.height);
58
+ style[`--hjm-switch-${kebab(name)}-thumb`] = rem(value.thumb);
59
+ style[`--hjm-switch-${kebab(name)}-inset`] = rem(value.inset);
60
+ style[`--hjm-switch-${kebab(name)}-offset`] = rem(value.width - value.thumb - value.inset * 2);
61
+ }
62
+ for (const [name, value] of Object.entries(listRowRecipe.density)) {
63
+ style[`--hjm-list-row-${kebab(name)}-one-line`] = rem(value.oneLineMinHeight);
64
+ style[`--hjm-list-row-${kebab(name)}-two-line`] = rem(value.twoLineMinHeight);
65
+ style[`--hjm-list-row-${kebab(name)}-padding-inline`] = rem(value.paddingHorizontal);
66
+ style[`--hjm-list-row-${kebab(name)}-padding-block`] = rem(value.paddingVertical);
67
+ }
48
68
  style["--hjm-control-min-touch-target"] = `${control.minTouchTarget}px`;
49
69
  style["--hjm-control-field-height"] = `${control.fieldHeight}px`;
70
+ style["--hjm-field-multiline-min-height"] = rem(fieldRecipe.multilineMinHeight);
71
+ style["--hjm-field-padding-block"] = rem(fieldRecipe.paddingVertical);
50
72
  for (const [name, value] of Object.entries(control.buttonHeight)) {
51
- style[`--hjm-control-button-${kebab(name)}`] = `${value}px`;
73
+ // The axis is applied to the emitted variables rather than to each rule so
74
+ // that every stylesheet consumer of a control height honours it at once.
75
+ style[`--hjm-control-button-${kebab(name)}`] =
76
+ `${visibleControlHeight(value, environment.minimumVisualTarget)}px`;
52
77
  }
53
78
  return style;
54
79
  }
package/dist/theme.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n control,\n fontFamily,\n fontWeight,\n motion,\n radius,\n spacing,\n typography,\n} from \"@hjmds/design-contracts/foundations\";\nimport type { DesignSystemProviderValue } from \"@hjmds/design-contracts/components/design-system-provider\";\nimport type { CSSProperties } from \"react\";\n\nexport type HjmThemeStyle = CSSProperties &\n Record<`--hjm-${string}`, string | number>;\n\nfunction kebab(value: string): string {\n return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n}\n\nfunction rem(value: number): string {\n return `${Number((value / 16).toFixed(5))}rem`;\n}\n\nexport function createHjmThemeStyle(\n value: DesignSystemProviderValue,\n): HjmThemeStyle {\n const { environment, palette } = value;\n const style: HjmThemeStyle = {\n \"--hjm-text-scale\": environment.textScale,\n \"--hjm-motion-scale\": environment.reducedMotion ? 0 : 1,\n colorScheme: environment.theme,\n backgroundColor: palette.theme.bg,\n color: palette.theme.text,\n };\n\n for (const [name, color] of Object.entries(palette.theme)) {\n style[`--hjm-color-${kebab(name)}`] = color;\n }\n for (const [name, color] of Object.entries(palette.statusAccents)) {\n style[`--hjm-accent-${kebab(name)}`] = color;\n }\n for (const [name, color] of Object.entries(palette.statusAccentFills)) {\n style[`--hjm-accent-fill-${kebab(name)}`] = color;\n }\n for (const [name, value] of Object.entries(spacing)) {\n style[`--hjm-space-${kebab(name)}`] = `${value}px`;\n }\n for (const [name, value] of Object.entries(radius)) {\n style[`--hjm-radius-${kebab(name)}`] = `${value}px`;\n }\n for (const [name, value] of Object.entries(typography)) {\n style[`--hjm-type-${kebab(name)}-size`] =\n `calc(${rem(value.fontSize)} * var(--hjm-text-scale))`;\n style[`--hjm-type-${kebab(name)}-line-height`] =\n `calc(${rem(value.lineHeight)} * var(--hjm-text-scale))`;\n style[`--hjm-type-${kebab(name)}-weight`] = value.fontWeight;\n }\n for (const [name, value] of Object.entries(fontWeight)) {\n style[`--hjm-font-weight-${kebab(name)}`] = value;\n }\n for (const [name, value] of Object.entries(motion)) {\n style[`--hjm-motion-${kebab(name)}`] = environment.reducedMotion\n ? \"0ms\"\n : `${value}ms`;\n }\n\n style[\"--hjm-font-family-ui\"] = fontFamily.ui.join(\", \");\n style[\"--hjm-control-min-touch-target\"] = `${control.minTouchTarget}px`;\n style[\"--hjm-control-field-height\"] = `${control.fieldHeight}px`;\n for (const [name, value] of Object.entries(control.buttonHeight)) {\n style[`--hjm-control-button-${kebab(name)}`] = `${value}px`;\n }\n\n return style;\n}\n"]}
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n control,\n fontFamily,\n fontWeight,\n motion,\n radius,\n spacing,\n typography,\n} from \"@hjmds/design-contracts/foundations\";\nimport {\n visibleControlHeight,\n type DesignSystemProviderValue,\n} from \"@hjmds/design-contracts/components/design-system-provider\";\nimport { fieldRecipe } from \"@hjmds/design-contracts/recipes/base\";\nimport { listRowRecipe, switchRecipe } from \"@hjmds/design-contracts/recipes\";\nimport type { CSSProperties } from \"react\";\n\nexport type HjmThemeStyle = CSSProperties &\n Record<`--hjm-${string}`, string | number>;\n\nfunction kebab(value: string): string {\n return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n}\n\nfunction rem(value: number): string {\n return `${Number((value / 16).toFixed(5))}rem`;\n}\n\nexport function createHjmThemeStyle(\n value: DesignSystemProviderValue,\n): HjmThemeStyle {\n const { environment, palette } = value;\n const style: HjmThemeStyle = {\n \"--hjm-text-scale\": environment.textScale,\n \"--hjm-motion-scale\": environment.reducedMotion ? 0 : 1,\n colorScheme: environment.theme,\n backgroundColor: palette.theme.bg,\n color: palette.theme.text,\n };\n\n for (const [name, color] of Object.entries(palette.theme)) {\n style[`--hjm-color-${kebab(name)}`] = color;\n }\n for (const [name, color] of Object.entries(palette.statusAccents)) {\n style[`--hjm-accent-${kebab(name)}`] = color;\n }\n for (const [name, color] of Object.entries(palette.statusAccentFills)) {\n style[`--hjm-accent-fill-${kebab(name)}`] = color;\n }\n for (const [name, value] of Object.entries(spacing)) {\n style[`--hjm-space-${kebab(name)}`] = `${value}px`;\n }\n for (const [name, value] of Object.entries(radius)) {\n style[`--hjm-radius-${kebab(name)}`] = `${value}px`;\n }\n for (const [name, value] of Object.entries(typography)) {\n style[`--hjm-type-${kebab(name)}-size`] =\n `calc(${rem(value.fontSize)} * var(--hjm-text-scale))`;\n style[`--hjm-type-${kebab(name)}-line-height`] =\n `calc(${rem(value.lineHeight)} * var(--hjm-text-scale))`;\n style[`--hjm-type-${kebab(name)}-weight`] = value.fontWeight;\n }\n for (const [name, value] of Object.entries(fontWeight)) {\n style[`--hjm-font-weight-${kebab(name)}`] = value;\n }\n for (const [name, value] of Object.entries(motion)) {\n style[`--hjm-motion-${kebab(name)}`] = environment.reducedMotion\n ? \"0ms\"\n : `${value}ms`;\n }\n\n style[\"--hjm-font-family-ui\"] = fontFamily.ui.join(\", \");\n // Row rhythm and the leading frame come from the recipe so the stylesheet\n // does not carry a second copy of the same numbers.\n style[\"--hjm-list-row-gap\"] = rem(listRowRecipe.gap);\n style[\"--hjm-list-row-leading-size\"] = rem(listRowRecipe.leadingSize);\n for (const [name, value] of Object.entries(switchRecipe.sizes)) {\n style[`--hjm-switch-${kebab(name)}-width`] = rem(value.width);\n style[`--hjm-switch-${kebab(name)}-height`] = rem(value.height);\n style[`--hjm-switch-${kebab(name)}-thumb`] = rem(value.thumb);\n style[`--hjm-switch-${kebab(name)}-inset`] = rem(value.inset);\n style[`--hjm-switch-${kebab(name)}-offset`] = rem(\n value.width - value.thumb - value.inset * 2,\n );\n }\n for (const [name, value] of Object.entries(listRowRecipe.density)) {\n style[`--hjm-list-row-${kebab(name)}-one-line`] = rem(value.oneLineMinHeight);\n style[`--hjm-list-row-${kebab(name)}-two-line`] = rem(value.twoLineMinHeight);\n style[`--hjm-list-row-${kebab(name)}-padding-inline`] = rem(value.paddingHorizontal);\n style[`--hjm-list-row-${kebab(name)}-padding-block`] = rem(value.paddingVertical);\n }\n style[\"--hjm-control-min-touch-target\"] = `${control.minTouchTarget}px`;\n style[\"--hjm-control-field-height\"] = `${control.fieldHeight}px`;\n style[\"--hjm-field-multiline-min-height\"] = rem(fieldRecipe.multilineMinHeight);\n style[\"--hjm-field-padding-block\"] = rem(fieldRecipe.paddingVertical);\n for (const [name, value] of Object.entries(control.buttonHeight)) {\n // The axis is applied to the emitted variables rather than to each rule so\n // that every stylesheet consumer of a control height honours it at once.\n style[`--hjm-control-button-${kebab(name)}`] =\n `${visibleControlHeight(value, environment.minimumVisualTarget)}px`;\n }\n\n return style;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hjmds/react",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "description": "Accessible React 19 renderers for HJM design contracts.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -140,7 +140,7 @@
140
140
  "react-dom": "19.2.3",
141
141
  "typescript": "^5.9.3",
142
142
  "vitest": "^4.1.10",
143
- "@hjmds/design-contracts": "0.9.4"
143
+ "@hjmds/design-contracts": "0.9.6"
144
144
  },
145
145
  "scripts": {
146
146
  "build": "tsc -p tsconfig.build.json && cp src/styles.css dist/styles.css",