@hypermedia-components/core 0.1.0 → 0.1.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.
@@ -64,6 +64,11 @@
64
64
  --hc-font-weight-semibold: 600;
65
65
  --hc-icon-size: 1em;
66
66
  --hc-opacity-disabled: 0.5;
67
+ --hc-shadow-sm: 0 1px 2px rgb(0, 0, 0, 0.15);
68
+ --hc-shadow-md: 0 4px 12px rgb(0, 0, 0, 0.1);
69
+ --hc-shadow-lg: 0 8px 24px rgb(0, 0, 0, 0.12);
70
+ --hc-shadow-overlay: 0 10px 30px rgb(0, 0, 0, 0.15);
71
+ --hc-shadow-edge: rgb(0, 0, 0, 0.2);
67
72
  }
68
73
 
69
74
  :root {
@@ -751,6 +756,11 @@
751
756
  --hc-color-status-error-bg: #450a0a;
752
757
  --hc-color-status-error-fg: #fecaca;
753
758
  --hc-color-status-error-border: #7f1d1d;
759
+ --hc-shadow-sm: 0 1px 2px rgb(0, 0, 0, 0.55);
760
+ --hc-shadow-md: 0 4px 12px rgb(0, 0, 0, 0.45);
761
+ --hc-shadow-lg: 0 8px 24px rgb(0, 0, 0, 0.5);
762
+ --hc-shadow-overlay: 0 10px 30px rgb(0, 0, 0, 0.6);
763
+ --hc-shadow-edge: rgb(0, 0, 0, 0.5);
754
764
  --hc-button-default-bg: #1f2937;
755
765
  --hc-button-default-fg: #f3f4f6;
756
766
  --hc-button-default-border: #374151;
@@ -64,6 +64,11 @@
64
64
  --hc-font-weight-semibold: 600;
65
65
  --hc-icon-size: 1em;
66
66
  --hc-opacity-disabled: 0.5;
67
+ --hc-shadow-sm: 0 1px 2px rgb(0, 0, 0, 0.15);
68
+ --hc-shadow-md: 0 4px 12px rgb(0, 0, 0, 0.1);
69
+ --hc-shadow-lg: 0 8px 24px rgb(0, 0, 0, 0.12);
70
+ --hc-shadow-overlay: 0 10px 30px rgb(0, 0, 0, 0.15);
71
+ --hc-shadow-edge: rgb(0, 0, 0, 0.2);
67
72
  }
68
73
 
69
74
  :root {
@@ -751,6 +756,11 @@
751
756
  --hc-color-status-error-bg: #450a0a;
752
757
  --hc-color-status-error-fg: #fecaca;
753
758
  --hc-color-status-error-border: #7f1d1d;
759
+ --hc-shadow-sm: 0 1px 2px rgb(0, 0, 0, 0.55);
760
+ --hc-shadow-md: 0 4px 12px rgb(0, 0, 0, 0.45);
761
+ --hc-shadow-lg: 0 8px 24px rgb(0, 0, 0, 0.5);
762
+ --hc-shadow-overlay: 0 10px 30px rgb(0, 0, 0, 0.6);
763
+ --hc-shadow-edge: rgb(0, 0, 0, 0.5);
754
764
  --hc-button-default-bg: #1f2937;
755
765
  --hc-button-default-fg: #f3f4f6;
756
766
  --hc-button-default-border: #374151;
package/dist/i18n.js CHANGED
@@ -45,7 +45,14 @@ export const DEFAULT_MESSAGES = Object.freeze({
45
45
  'toast.label': 'Notifications',
46
46
  });
47
47
 
48
- let messages = { ...DEFAULT_MESSAGES };
48
+ // The dist bundles (hc.min.js, hc.behaviors.min.js) each inline a copy of
49
+ // this module, so module-level state would be one catalog per bundle —
50
+ // setMessages() through one entry would never reach behaviors loaded from
51
+ // another (#216). The catalog lives on a globalThis-keyed singleton instead,
52
+ // so every copy reads and writes the same state.
53
+ const STATE_KEY = Symbol.for('hypermedia-components.i18n');
54
+ const state =
55
+ globalThis[STATE_KEY] || (globalThis[STATE_KEY] = { messages: { ...DEFAULT_MESSAGES } });
49
56
 
50
57
  /**
51
58
  * Merge translations into the global catalog. Pass a flat `{ key: value }`
@@ -57,10 +64,10 @@ let messages = { ...DEFAULT_MESSAGES };
57
64
  * @returns {() => void} restore
58
65
  */
59
66
  export function setMessages(overrides) {
60
- const prev = messages;
61
- messages = { ...messages, ...(overrides || {}) };
67
+ const prev = state.messages;
68
+ state.messages = { ...state.messages, ...(overrides || {}) };
62
69
  return () => {
63
- messages = prev;
70
+ state.messages = prev;
64
71
  };
65
72
  }
66
73
 
@@ -68,7 +75,7 @@ export function setMessages(overrides) {
68
75
  * Reset the catalog to the built-in English defaults.
69
76
  */
70
77
  export function resetMessages() {
71
- messages = { ...DEFAULT_MESSAGES };
78
+ state.messages = { ...DEFAULT_MESSAGES };
72
79
  }
73
80
 
74
81
  /**
@@ -77,7 +84,7 @@ export function resetMessages() {
77
84
  * @returns {Record<string, string>}
78
85
  */
79
86
  export function getMessages() {
80
- return { ...messages };
87
+ return { ...state.messages };
81
88
  }
82
89
 
83
90
  /**
@@ -90,7 +97,7 @@ export function getMessages() {
90
97
  * @returns {boolean}
91
98
  */
92
99
  export function hasMessage(key) {
93
- return messages[key] != null || DEFAULT_MESSAGES[key] != null;
100
+ return state.messages[key] != null || DEFAULT_MESSAGES[key] != null;
94
101
  }
95
102
 
96
103
  /**
@@ -103,7 +110,7 @@ export function hasMessage(key) {
103
110
  * @returns {string}
104
111
  */
105
112
  export function t(key, params) {
106
- let str = messages[key];
113
+ let str = state.messages[key];
107
114
  if (str == null) str = DEFAULT_MESSAGES[key];
108
115
  if (str == null) str = key;
109
116
  if (params) {
package/dist/index.d.ts CHANGED
@@ -30,5 +30,5 @@ export { installValidation } from "./validation.js";
30
30
  export { installThemeToggle } from "./theme-toggle.js";
31
31
  export { installFieldErrors } from "./field-errors.js";
32
32
  export { installChart } from "./chart.js";
33
- export const version: "0.1.0";
33
+ export const version: "0.1.1";
34
34
  export { setMessages, resetMessages, getMessages, hasMessage, DEFAULT_MESSAGES } from "./i18n.js";
package/dist/index.js CHANGED
@@ -44,4 +44,4 @@ export { installChart } from './chart.js';
44
44
  // ARIA labels). Call setMessages() once at startup, before installing.
45
45
  export { setMessages, resetMessages, getMessages, hasMessage, DEFAULT_MESSAGES } from './i18n.js';
46
46
 
47
- export const version = '0.1.0';
47
+ export const version = '0.1.1';
@@ -0,0 +1,3 @@
1
+ export default ja;
2
+ /** @type {Readonly<Record<string, string>>} */
3
+ declare const ja: Readonly<Record<string, string>>;
@@ -0,0 +1,44 @@
1
+ // @hypermedia-components/core — Japanese locale pack.
2
+ //
3
+ // A complete translation of DEFAULT_MESSAGES (../i18n.js): every string a
4
+ // behavior can inject. Pass it to setMessages() once at startup, before
5
+ // behaviors install:
6
+ //
7
+ // import { setMessages } from '@hypermedia-components/core/i18n';
8
+ // import ja from '@hypermedia-components/core/locales/ja';
9
+ // setMessages(ja);
10
+ //
11
+ // App-specific wording can be layered on top with a second setMessages()
12
+ // call — later merges win.
13
+ //
14
+ // Completeness is enforced by test/locales.test.mjs: a pack must cover
15
+ // every DEFAULT_MESSAGES key (and carry no stale ones), so a behavior that
16
+ // adds keys fails CI until every shipped pack translates them.
17
+
18
+ /** @type {Readonly<Record<string, string>>} */
19
+ const ja = Object.freeze({
20
+ 'combobox.empty': '一致する項目がありません',
21
+ 'combobox.loading': '読み込み中…',
22
+ 'combobox.error': '選択肢を読み込めませんでした',
23
+ 'combobox.create': '「{value}」を作成',
24
+ 'multicombobox.empty': '一致する項目がありません',
25
+ 'multicombobox.create': '「{value}」を追加',
26
+ 'multicombobox.remove': '{label} を削除',
27
+ 'calendar.label': 'カレンダー',
28
+ 'calendar.prevMonth': '前の月',
29
+ 'calendar.nextMonth': '次の月',
30
+ 'calendar.month': '月',
31
+ 'calendar.year': '年',
32
+ 'confirm.message': '続行しますか?',
33
+ 'confirm.title': '確認',
34
+ 'confirm.confirm': '実行',
35
+ 'confirm.cancel': 'キャンセル',
36
+ 'fieldErrors.unknown': '入力値が正しくありません',
37
+ 'shell.toggleNav': 'ナビゲーションを開閉',
38
+ 'shell.collapseNav': 'サイドバーを折りたたむ',
39
+ 'splitter.resize': 'パネルの幅を変更',
40
+ 'themeToggle.label': 'カラーテーマを切り替え',
41
+ 'toast.label': '通知',
42
+ });
43
+
44
+ export default ja;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypermedia-components/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Semantic components and recipes for hypermedia applications.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,6 +29,10 @@
29
29
  "types": "./dist/i18n.d.ts",
30
30
  "import": "./dist/i18n.js"
31
31
  },
32
+ "./locales/*": {
33
+ "types": "./dist/locales/*.d.ts",
34
+ "import": "./dist/locales/*.js"
35
+ },
32
36
  "./css": "./dist/hc.css",
33
37
  "./css/min": "./dist/hc.min.css",
34
38
  "./css/core": "./dist/hc.core.css",
@@ -79,14 +83,14 @@
79
83
  "@axe-core/playwright": "^4.11.3",
80
84
  "@eslint/js": "^10.0.1",
81
85
  "@playwright/test": "^1.60.0",
82
- "esbuild": "^0.28.0",
83
- "eslint": "^10.4.0",
86
+ "esbuild": "^0.28.1",
87
+ "eslint": "^10.4.1",
84
88
  "globals": "^17.6.0",
85
89
  "jsdom": "^29.1.1",
86
- "stylelint": "^17.12.0",
90
+ "stylelint": "^17.13.0",
87
91
  "stylelint-config-standard": "^40.0.0",
88
92
  "typescript": "^6.0.3",
89
- "vitest": "^4.1.7"
93
+ "vitest": "^4.1.8"
90
94
  },
91
95
  "scripts": {
92
96
  "build": "pnpm run build:tokens && pnpm run build:css && pnpm run build:types && pnpm run build:js && pnpm run build:min",
@@ -100,6 +104,7 @@
100
104
  "test:browser": "pnpm run build && playwright test",
101
105
  "lint": "pnpm run lint:js && pnpm run lint:css",
102
106
  "lint:js": "eslint .",
103
- "lint:css": "stylelint \"src/css/**/*.css\""
107
+ "lint:css": "stylelint \"src/css/**/*.css\"",
108
+ "lint:fix": "eslint . --fix && stylelint \"src/css/**/*.css\" --fix"
104
109
  }
105
110
  }
@@ -3,8 +3,16 @@
3
3
  DTCG-shaped JSON sources. Four layers:
4
4
 
5
5
  1. `primitive.tokens.json` — raw values (color scales, spacing, radii, font sizes).
6
- 2. `semantic.tokens.json` — UI meaning (bg, surface, text, border, action.primary).
6
+ 2. `semantic.tokens.json` — UI meaning (bg, surface, text, border, action.primary,
7
+ the `shadow.*` elevation scale).
7
8
  3. `component.tokens.json` — component values (button height, input border, card radius).
8
9
  4. `theme.*.tokens.json` and `density.*.tokens.json` — light/dark, comfortable/compact/dense.
9
10
 
10
11
  The build emits `dist/hc.tokens.css` with `--hc-*` custom properties.
12
+
13
+ Values are CSS strings. Composite values (the `shadow.*` scale,
14
+ `color.overlay`'s `rgba()`) are stored as the literal CSS string — the
15
+ transformer emits `$value` verbatim and resolves embedded `{refs}`, it
16
+ does not understand DTCG composite objects. Component CSS reads the
17
+ elevation scale directly (`box-shadow: var(--hc-shadow-lg)`); the dark
18
+ theme overrides the four steps with stronger alphas.
@@ -102,5 +102,13 @@
102
102
  },
103
103
  "opacity": {
104
104
  "disabled": { "$type": "number", "$value": "0.5" }
105
+ },
106
+ "shadow": {
107
+ "$description": "Elevation scale. CSS string composites — the transformer emits $value verbatim (same pragmatic shape as color.overlay). Dark overrides live in theme.dark.tokens.json.",
108
+ "sm": { "$type": "shadow", "$value": "0 1px 2px rgb(0, 0, 0, 0.15)" },
109
+ "md": { "$type": "shadow", "$value": "0 4px 12px rgb(0, 0, 0, 0.1)" },
110
+ "lg": { "$type": "shadow", "$value": "0 8px 24px rgb(0, 0, 0, 0.12)" },
111
+ "overlay": { "$type": "shadow", "$value": "0 10px 30px rgb(0, 0, 0, 0.15)" },
112
+ "edge": { "$type": "color", "$value": "rgb(0, 0, 0, 0.2)" }
105
113
  }
106
114
  }
@@ -46,5 +46,13 @@
46
46
  "border": { "$type": "color", "$value": "{primitive.color.red.900}" }
47
47
  }
48
48
  }
49
+ },
50
+ "shadow": {
51
+ "$description": "Stronger alphas than the light scale so elevation stays legible on dark surfaces.",
52
+ "sm": { "$type": "shadow", "$value": "0 1px 2px rgb(0, 0, 0, 0.55)" },
53
+ "md": { "$type": "shadow", "$value": "0 4px 12px rgb(0, 0, 0, 0.45)" },
54
+ "lg": { "$type": "shadow", "$value": "0 8px 24px rgb(0, 0, 0, 0.5)" },
55
+ "overlay": { "$type": "shadow", "$value": "0 10px 30px rgb(0, 0, 0, 0.6)" },
56
+ "edge": { "$type": "color", "$value": "rgb(0, 0, 0, 0.5)" }
49
57
  }
50
58
  }