@godxjp/ui 2.2.0 → 5.0.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.
Files changed (47) hide show
  1. package/BRAND.md +39 -29
  2. package/CHANGELOG.md +554 -10
  3. package/README.md +143 -168
  4. package/config/eslint.js +54 -0
  5. package/config/prettier.cjs +20 -0
  6. package/config/tsconfig.base.json +22 -0
  7. package/config/vitest.base.ts +26 -0
  8. package/dist/MiniMonth-YAmPGEpC.d.ts +143 -0
  9. package/dist/Table.types-BbsxoIYE.d.ts +352 -0
  10. package/dist/color-DO0qqUAb.d.ts +38 -0
  11. package/dist/components/composites.d.ts +963 -0
  12. package/dist/components/composites.js +7340 -0
  13. package/dist/components/composites.js.map +1 -0
  14. package/dist/components/primitives.d.ts +2633 -163
  15. package/dist/components/primitives.js +7264 -165
  16. package/dist/components/primitives.js.map +1 -1
  17. package/dist/components/shell.d.ts +82 -12
  18. package/dist/components/shell.js +168 -162
  19. package/dist/components/shell.js.map +1 -1
  20. package/dist/hooks.d.ts +83 -8
  21. package/dist/hooks.js +497 -83
  22. package/dist/hooks.js.map +1 -1
  23. package/dist/i18n.d.ts +55 -3
  24. package/dist/i18n.js +456 -5
  25. package/dist/i18n.js.map +1 -1
  26. package/dist/index.d.ts +24 -5
  27. package/dist/index.js +12522 -267
  28. package/dist/index.js.map +1 -1
  29. package/dist/padding-DY0JV5Ja.d.ts +16 -0
  30. package/dist/preferences.d.ts +132 -0
  31. package/dist/preferences.js +262 -0
  32. package/dist/preferences.js.map +1 -0
  33. package/dist/props.d.ts +86 -0
  34. package/dist/props.js +16 -0
  35. package/dist/props.js.map +1 -0
  36. package/dist/size-CQwNvOWd.d.ts +19 -0
  37. package/dist/{data.d.ts → types-LTj-2bl-.d.ts} +7 -12
  38. package/dist/useTableViews-D5NIAJ7h.d.ts +154 -0
  39. package/package.json +92 -35
  40. package/src/tokens/tailwind.css +158 -0
  41. package/dist/components/screens.d.ts +0 -51
  42. package/dist/components/screens.js +0 -806
  43. package/dist/components/screens.js.map +0 -1
  44. package/dist/data.js +0 -93
  45. package/dist/data.js.map +0 -1
  46. package/src/tokens/tokens-ext.css +0 -401
  47. package/src/tokens/tokens.css +0 -765
package/README.md CHANGED
@@ -1,206 +1,181 @@
1
- # @godxjp/ui — GoDX Forge unified design system
1
+ # @godxjp/ui
2
2
 
3
- **Status:** core source of truth. **Every frontend in the GoDX
4
- ecosystem MUST consume this package.** No service may bring its own
5
- tokens, theme, color palette, i18n provider, or component primitives.
6
- This rule is review-blocking (see `MUST RULES` below).
3
+ **Version 3.0.0** GoDX professional UI framework
7
4
 
8
- The only thing a service is allowed to do differently from another is
9
- **layout**: route tree, page composition, screen-specific widgets that
10
- have no equivalent in another service. Everything visual — typography,
11
- color, spacing, density, dark mode, language switcher, sidebar shape,
12
- top-bar shape, buttons, badges, kanban, KPI tiles, modal pattern — comes
13
- from here.
5
+ [![npm](https://img.shields.io/npm/v/@godxjp/ui)](https://www.npmjs.com/package/@godxjp/ui)
6
+ [![License](https://img.shields.io/github/license/godx-jp/godxjp-ui)](LICENSE)
7
+ [![Types included](https://img.shields.io/badge/types-included-blue)](src/)
14
8
 
15
- ---
9
+ `@godxjp/ui` is the **single source of visual truth** for the GoDX platform.
10
+ Every service frontend (admin-platform, forge-service, console-service, me-service,
11
+ chat-service, knowledge-service, …) consumes this package. No service reimplements
12
+ a button, dialog, sidebar, or design token.
16
13
 
17
- ## MUST RULES (review-blocking)
14
+ The framework enforces three Japanese-enterprise design principles:
18
15
 
19
- > If a PR violates any of these the reviewer rejects, regardless of
20
- > deadline. Sync the visual layer first, ship the feature after.
21
-
22
- 1. **Tokens.** Every frontend imports `@godxjp/ui/tokens.css` AND
23
- `@godxjp/ui/tokens-ext.css` from its root entry (`main.tsx` /
24
- `app.tsx`). Services do not define their own `--background`,
25
- `--foreground`, `--primary`, font stack, density variables, or
26
- shadow scale. Tenant overrides happen via `[data-tenant="<id>"]`
27
- on `<html>`, never per-service.
28
-
29
- 2. **Stack.** TypeScript + React 19 + Vite + Tailwind v4 + shadcn-style
30
- primitives (Radix + cva + tailwind-merge). Components from this
31
- package are the only UI atoms a service uses. No service may ship
32
- `@mui/material`, `chakra-ui`, `antd`, native `styled-components`,
33
- raw `<input>` with custom CSS, etc.
34
-
35
- 3. **i18n.** All translation goes through `@godxjp/ui/i18n` — a single
36
- pre-configured `i18next` instance with auto-detect + JA fallback +
37
- localStorage persistence. The base dictionary (nav, shell, common,
38
- tweaks, kpi, pdca, issue) lives in `src/i18n/locales/{ja,en,vi}.ts`
39
- and is exported as `ForgeTranslations`. Services may register their
40
- own namespace (e.g. `i18n.addResourceBundle("ja", "sandbox", {…})`)
41
- but never replace the base.
42
-
43
- 4. **Locale set.** Supported: `ja` (default), `en`, `vi`. Adding a
44
- locale = PR to this package, never per-service.
45
-
46
- 5. **Theme + density + tenant.** All toggled via the `useTweaks` hook
47
- from `@godxjp/ui/hooks`. The hook mirrors selections onto `<html>`
48
- data attributes — services rely on those, they do not maintain
49
- their own theme state.
50
-
51
- 6. **Fonts.** `M PLUS 2` (loaded by `tokens.css`) is the primary face;
52
- fallbacks are Hiragino → Yu Gothic → Noto Sans JP → system. No
53
- service may swap in `Inter`, `Roboto`, `Comic Sans`, etc.
54
-
55
- 7. **Color literals.** No hex / rgb / oklch literals in service code.
56
- Always reference a CSS variable: `var(--primary)`, `var(--wa-akane)`,
57
- `text-foreground`, `bg-surface-2`. The 13 `--wa-*` 和色 colors are
58
- for charts + decoration ONLY; never role-map them.
59
-
60
- 8. **Density.** Three modes only: `compact` (28 px element), `default`
61
- (32 px), `comfortable` (44 px, WCAG-friendly). No `medium`, no
62
- intermediate sizes. Components honor `--density-element-*` tokens.
63
-
64
- 9. **Signal palette.** 5 colors with fixed semantics — `--success`
65
- (若竹 wakatake), `--warning` (山吹 yamabuki), `--info` (群青
66
- gunjō), `--error/destructive` (茜 akane), `--attention` (朱 shu).
67
- **Red (`--destructive`) is reserved for destructive actions only.**
68
- Don't use `--destructive` for "wrong answer" badges, validation
69
- chrome, or general emphasis.
70
-
71
- 10. **No emojis in product UI.** Iconography uses `lucide-react`.
72
- Emoji are acceptable in user-generated content (comments, chat,
73
- notifications) but never in chrome.
74
-
75
- 11. **Shell layout.** When a service needs a sidebar + topbar shell,
76
- it imports `<AppShell>` from `@godxjp/ui/components/shell` and
77
- plugs in its own nav config + screen routes. Services do not
78
- hand-roll a CSS grid for the chrome.
79
-
80
- 12. **Switchers (product/project) are universal.** The Linear-style
81
- quick switcher is one component, used everywhere — same data
82
- shape (`ForgeProduct` / `ForgeProject` from `@godxjp/ui/data`).
83
- A service that doesn't have a project concept passes
84
- `project={null}`; the chip auto-hides.
16
+ | Principle | Meaning | What it enforces |
17
+ |---|---|---|
18
+ | **渋み** (shibumi) | Restrained elegance | OKLCH primary chroma ≤ 0.18. No neon. No gradients on functional UI. |
19
+ | **間** (ma) | Vertical breathing room | Body `line-height: 1.7`. Generous spacing. Density toggle for dense tables. |
20
+ | **簡素** (kanso) | Simplicity | Three font weights: 400 (body), 500 (heading), 700 (emphasis). No 600 in new code. |
85
21
 
86
22
  ---
87
23
 
88
- ## Layout boundary — what a service CAN do without violating
24
+ ## Quick start
89
25
 
90
- | Service-owned | Must come from `@godxjp/ui` |
91
- |---|---|
92
- | Route tree (`react-router-dom` config) | Visual atoms: button, badge, card, KPI, kanban col |
93
- | Page composition (what cards live on this screen) | Shell: sidebar + topbar + tweaks panel |
94
- | Screen-specific widgets (e.g. a domain-pool map view that no other service has) | Theme tokens, density, dark mode |
95
- | Domain data shapes (e.g. the sandbox's tmux pane object) | i18n provider, locale list, base dictionary |
96
- | Per-service API client | Color palette, font stack, spacing scale |
26
+ A new service needs three lines to be fully brand-compliant:
97
27
 
98
- If a screen requires a NEW primitive that another service might also
99
- need, add it to this package first, then consume it. Don't fork.
28
+ ```tsx
29
+ // services/<slug>-service/frontend/src/main.tsx
30
+ import "@godxjp/ui/tailwind.css" // tokens + Tailwind v4 utilities — ONE import
31
+ import { initI18n } from "@godxjp/ui/i18n"
32
+ import { AppShell, Sidebar, Topbar } from "@godxjp/ui/components/shell"
100
33
 
101
- ---
34
+ initI18n()
102
35
 
103
- ## Adoption tracker
36
+ createRoot(document.getElementById("root")!).render(
37
+ <BrowserRouter>
38
+ <AppShell sidebar={<Sidebar nav={MY_NAV} />} topbar={<Topbar />}>
39
+ <Routes>{/* service-specific routes */}</Routes>
40
+ </AppShell>
41
+ </BrowserRouter>,
42
+ )
43
+ ```
104
44
 
105
- Each service must reach **100% token coverage** before it's allowed
106
- to claim "GoDX Forge compliant" in its README:
45
+ That is the entire integration surface. No theming step. No per-service token file.
107
46
 
108
- | Service | Status | Owner | Notes |
109
- |---|---|---|---|
110
- | `forge-service/frontend` | adopting (phase 1) | platform | Reference implementation. |
111
- | `admin-platform/frontend` | partial (existing Omnify tokens overlap ~90%) | platform | Migrate before Plan #19 cut-over. |
112
- | `me-service/frontend` | not started | platform | Tracked under Plan #31 R6. |
113
- | `console-service/frontend` | not started | platform | Tracked under Plan #31 R6. |
114
- | `agent-service/frontend` | not started | platform | Plan #21 G17 finished embed; visual port pending. |
115
- | `knowledge-service/frontend` | not started | knowledge | Plan #18 K-phase polish. |
47
+ ---
116
48
 
117
- Operator-side dashboards (Grafana, Mailpit, etc.) are external — they
118
- keep their own UI, not in scope.
49
+ ## Zero-config toolchain
119
50
 
120
- ---
51
+ Per the umbrella's frontend-architecture spec (zero-config principle), services
52
+ inherit the full toolchain from this package:
121
53
 
122
- ## What lives here
54
+ ```js
55
+ // eslint.config.js — one line
56
+ export { default } from "@godxjp/ui/eslint-config"
57
+ ```
123
58
 
59
+ ```json
60
+ // package.json
61
+ "prettier": "@godxjp/ui/prettier-config"
124
62
  ```
125
- packages/godxjp-ui/src/
126
- ├── tokens/ Source of truth for CSS variables.
127
- │ ├── tokens.css Base palette, type scale, density,
128
- │ │ shadows, motion. Imports M PLUS 2.
129
- │ └── tokens-ext.css Sidebar, topbar, page, card, badge,
130
- │ kanban, dark mode, tenant overrides.
131
-
132
- ├── i18n/ i18next bootstrap + base dictionary.
133
- │ ├── index.ts initI18n(); auto-detect + JA fallback.
134
- │ └── locales/{ja,en,vi}.ts `ForgeTranslations` shape.
135
-
136
- ├── hooks/
137
- │ └── useTweaks.ts density / theme / tenant / locale /
138
- │ sidebar-collapsed state w/ persistence.
139
-
140
- ├── data/
141
- │ └── products.ts ForgeProduct / ForgeProject types +
142
- │ mock fixture (until forge-service
143
- │ /api/v1/orgs/ wires real data).
144
-
145
- ├── primitives/ shadcn-styled atoms (button, badge,
146
- │ card, kbd, ...). One copy across the
147
- │ org.
148
-
149
- └── components/shell/ AppShell, Sidebar, Topbar,
150
- ProductSwitcher, ProjectSwitcher,
151
- TweaksPanel, CommandPalette.
63
+
64
+ ```json
65
+ // tsconfig.json
66
+ { "extends": "@godxjp/ui/tsconfig" }
67
+ ```
68
+
69
+ ```ts
70
+ // vitest.config.ts
71
+ import base from "@godxjp/ui/vitest-config"
72
+ import { mergeConfig } from "vitest/config"
73
+ export default mergeConfig(base, { test: {} })
152
74
  ```
153
75
 
154
76
  ---
155
77
 
156
- ## How to consume from a service frontend
78
+ ## Import surface
157
79
 
158
- ```tsx
159
- // services/<svc>/frontend/src/main.tsx
160
- import "@godxjp/ui/tokens.css";
161
- import "@godxjp/ui/tokens-ext.css";
162
- import { initI18n } from "@godxjp/ui/i18n";
163
- import { AppShell, Sidebar, Topbar } from "@godxjp/ui/components/shell";
80
+ | Import | What you get |
81
+ |---|---|
82
+ | `@godxjp/ui` | All primitives + hooks + i18n helpers (barrel) |
83
+ | `@godxjp/ui/tailwind.css` | Tailwind v4 + design tokens + base styles |
84
+ | `@godxjp/ui/tokens.css` | Raw CSS custom properties only (no Tailwind) |
85
+ | `@godxjp/ui/tokens-ext.css` | Extended tokens (dark mode, tenants, sidebar vars) |
86
+ | `@godxjp/ui/sonner.css` | Sonner toast animations (import after tokens) |
87
+ | `@godxjp/ui/components/primitives` | All primitives — see [`src/components/primitives.ts`](src/components/primitives.ts) (single barrel; 73+ surfaces re-exported from six group folders per cardinal rule 27) |
88
+ | `@godxjp/ui/components/shell` | `AppShell`, `Sidebar`, `Topbar`, `TweaksPanel`, `CommandPalette`, `ProductSwitcher`, `ProjectSwitcher`, `PageContent` |
89
+ | `@godxjp/ui/components/composites` | Upload family, `MediaUpload`, `AvatarUploader`, `LocaleInput`, calendar app composite |
90
+ | `@godxjp/ui/i18n` | `initI18n()`, `SUPPORTED_LOCALES`, `GodxLocale` |
91
+ | `@godxjp/ui/hooks` | `useTweaks()`, `Tweaks`, `Density`, `Theme` |
92
+ | `@godxjp/ui/preferences` | `PreferencesProvider` — locale + timezone React context |
93
+ | `@godxjp/ui/eslint-config` | Shared ESLint flat config |
94
+ | `@godxjp/ui/prettier-config` | Shared Prettier config |
95
+ | `@godxjp/ui/tsconfig` | Strict TypeScript base |
96
+ | `@godxjp/ui/vitest-config` | Vitest base with jsdom + coverage thresholds |
164
97
 
165
- initI18n();
98
+ ---
166
99
 
167
- createRoot(document.getElementById("root")!).render(
168
- <BrowserRouter>
169
- <AppShell sidebar={<Sidebar nav={MY_NAV} />} topbar={<Topbar />}>
170
- <Routes>{/* service-specific routes */}</Routes>
171
- </AppShell>
172
- </BrowserRouter>,
173
- );
174
- ```
100
+ ## Primitives (v3)
175
101
 
176
- That's the entire integration surface for a new service.
102
+ | Component | Radix backing | A11y | Status |
103
+ |---|---|---|---|
104
+ | `Badge` | — | WCAG 2.1 AA | production |
105
+ | `Button` | `@radix-ui/react-slot` | focus-visible, keyboard | production |
106
+ | `Card` | — | — | production |
107
+ | `Input`, `Textarea` | — | aria-invalid, label wire | production |
108
+ | `Label` | `@radix-ui/react-label` | for/id | production |
109
+ | `Tabs`, `Tabs`, `Tabs`, `Tabs` | `@radix-ui/react-tabs` | roving tabindex | production |
110
+ | `Avatar` | — | aria-label | production |
111
+ | `Separator` | `@radix-ui/react-separator` | role separator | production |
112
+ | `Popover`, `Popover`, `Popover` | `@radix-ui/react-popover` | focus trap | production |
113
+ | `DropdownMenu` family | `@radix-ui/react-dropdown-menu` | keyboard nav | production |
114
+ | `Calendar` | `react-day-picker` | ARIA grid | production |
115
+ | `TimeInput` | — | aria-invalid | production |
116
+ | `Dialog` family | `@radix-ui/react-dialog` | focus trap, aria-modal | production |
117
+ | `Sheet` family | `@radix-ui/react-dialog` | focus trap, aria-modal | production |
118
+ | `AlertDialog` family | `@radix-ui/react-alert-dialog` | focus trap | production |
119
+ | `Select` family | `@radix-ui/react-select` | keyboard nav | production |
120
+ | `Switch` | `@radix-ui/react-switch` | role switch | production |
121
+ | `Checkbox` | `@radix-ui/react-checkbox` | role checkbox | production |
122
+ | `Table` family | — | role table | production |
123
+ | `Combobox` family | `cmdk` + Popover | keyboard nav | production |
124
+ | `Toaster`, `toast` | `sonner` | aria-live | production |
125
+ | `Skeleton` | — | aria-hidden | production |
126
+ | `Breadcrumb`, `Breadcrumb`, `Breadcrumb` | — | aria-label, aria-current | production |
177
127
 
178
128
  ---
179
129
 
180
- ## Versioning + change control
130
+ ## i18n
181
131
 
182
- The package follows semver. Breaking changes (renamed token, removed
183
- component prop, changed default tenant) require:
132
+ Mandatory locales per the umbrella frontend-architecture spec §6:
184
133
 
185
- 1. RFC issue in `godx-platform-sdk` repo (or local `docs/plans/` if
186
- pre-extraction).
187
- 2. Cross-service audit which surfaces break, who fixes them.
188
- 3. Major version bump.
134
+ | Locale | Status |
135
+ |---|---|
136
+ | `ja` | production (primary) |
137
+ | `en` | production |
138
+ | `vi` | production |
139
+ | `fil` | production (added v3.0.0) |
189
140
 
190
- Additive changes (new component, new locale string, new wa-iro color,
191
- new tenant) are minor / patch — no RFC needed.
141
+ Services add extra namespaces via `i18n.addResourceBundle(locale, "my-ns", {…})`.
192
142
 
193
- Issue / PR for changes: file under `godx-jp/godx-platform-sdk` repo
194
- once Plan #22 extraction completes; until then file under
195
- `godx-jp/godx-admin` with label `area:design-system`.
143
+ ---
144
+
145
+ ## MUST RULES (review-blocking)
146
+
147
+ See [`README.md § MUST RULES`](README.md) and [`BRAND.md`](BRAND.md) for the full list.
148
+ The short version:
149
+
150
+ 1. Import `@godxjp/ui/tailwind.css` (or `/tokens.css`) once at app entry.
151
+ 2. Never redefine `--primary`, `--foreground`, `--background`, or any base token in app code.
152
+ 3. Per-deployment brand-color overrides live under `[data-accent="<palette>"]` in a service `theme.css` (per cardinal rule 19 — `[data-tenant]` is removed).
153
+ 4. No `@mui/material`, `chakra-ui`, `antd`, or any other component library.
154
+ 5. All primitive needs → add to `@godxjp/ui` first, then consume.
155
+ 6. Shell (AppShell + Sidebar + Topbar) is one component set — no hand-rolled grids.
156
+
157
+ ---
158
+
159
+ ## Adoption tracker
160
+
161
+ | Service | Status | Notes |
162
+ |---|---|---|
163
+ | `calendar-service/frontend` | adopted | Greenfield; compliant from first commit. |
164
+ | `forge-service/frontend` | adopting (phase 1) | Reference implementation for migration pattern. |
165
+ | `admin-platform/frontend` | partial | Omnify tokens overlap ~90%; full migration pending. |
166
+ | `me-service/frontend` | adopting | Plan #31 R6 — active migration. |
167
+ | `console-service/frontend` | adopting | Epic #1412; AppShell + tokens wired. |
168
+ | `agent-service/frontend` | not started | Plan #21 G17. |
169
+ | `knowledge-service/frontend` | not started | Plan #18 K-phase. |
170
+ | `chat-service/frontend` | adopting | Plan #30 completion phase. |
196
171
 
197
172
  ---
198
173
 
199
- ## See also
174
+ ## Versioning
175
+
176
+ `@godxjp/ui` follows [Semantic Versioning](https://semver.org/).
177
+ Breaking changes require a cross-service audit + major bump.
178
+ See [`CHANGELOG.md`](CHANGELOG.md) for the full history.
200
179
 
201
- - Design prototype the package is ported from: `chat1.md` + `chat2.md`
202
- (Claude Design handoff, 2026-05-08 / 2026-05-09).
203
- - Plan #19 — forge-service extraction.
204
- - Plan #22 — multi-repo standalone services. `@godxjp/ui` is the
205
- TypeScript counterpart to `godx-platform-sdk` (Go shared kernel).
206
- - Plan #31 R6 — per-portal UI alignment.
180
+ Source: `github.com/godx-jp/godxjp-ui` (Apache-2.0).
181
+ The umbrella repo (`godx-jp/godx-admin`) pins this as a git submodule at `libs/ts/godxjp-ui/`.
@@ -0,0 +1,54 @@
1
+ // @godxjp/ui — shared ESLint flat config.
2
+ //
3
+ // Consume in a service frontend with a single line:
4
+ //
5
+ // // eslint.config.js
6
+ // export { default } from "@godxjp/ui/eslint-config"
7
+ //
8
+ // Locked stack (umbrella frontend-architecture spec §9):
9
+ // ESLint 9.x + typescript-eslint 8.x (strict + stylistic)
10
+ // eslint-plugin-react 7.x + eslint-plugin-react-hooks 5.x
11
+ // eslint-plugin-jsx-a11y 6.x (WCAG 2.1 AA in JSX)
12
+ // eslint-config-prettier (turns off formatting conflicts)
13
+ //
14
+ // This file is intentionally kept dependency-free at the @godxjp/ui level
15
+ // so it can be consumed before peerDependencies install. The locked rule
16
+ // sets above are declared as peerDependencies by the consumer's package.json;
17
+ // when a service uses the umbrella workspace those peers resolve automatically.
18
+
19
+ /** @type {import("eslint").Linter.Config[]} */
20
+ const config = [
21
+ {
22
+ // Global ignores — applies before any rules.
23
+ ignores: ["dist/**", "node_modules/**", "*.d.ts"],
24
+ },
25
+ {
26
+ files: ["**/*.{ts,tsx}"],
27
+ languageOptions: {
28
+ parserOptions: {
29
+ ecmaVersion: "latest",
30
+ sourceType: "module",
31
+ ecmaFeatures: { jsx: true },
32
+ },
33
+ },
34
+ rules: {
35
+ // React 19 does not require the React import for JSX.
36
+ "react/react-in-jsx-scope": "off",
37
+ // Always exhaustive deps.
38
+ "react-hooks/exhaustive-deps": "warn",
39
+ // Accessibility baseline.
40
+ "jsx-a11y/alt-text": "error",
41
+ "jsx-a11y/aria-props": "error",
42
+ "jsx-a11y/aria-proptypes": "error",
43
+ "jsx-a11y/aria-unsupported-elements": "error",
44
+ "jsx-a11y/role-has-required-aria-props": "error",
45
+ "jsx-a11y/role-supports-aria-props": "error",
46
+ "jsx-a11y/interactive-supports-focus": "warn",
47
+ "jsx-a11y/click-events-have-key-events": "warn",
48
+ // No console in production code.
49
+ "no-console": ["warn", { allow: ["warn", "error"] }],
50
+ },
51
+ },
52
+ ]
53
+
54
+ export default config
@@ -0,0 +1,20 @@
1
+ // @godxjp/ui — shared Prettier config.
2
+ //
3
+ // Consume in a service frontend:
4
+ // // .prettierrc.json → "prettier": "@godxjp/ui/prettier-config"
5
+ // // or package.json: "prettier": "@godxjp/ui/prettier-config"
6
+
7
+ /** @type {import("prettier").Config} */
8
+ module.exports = {
9
+ semi: false,
10
+ singleQuote: false,
11
+ trailingComma: "all",
12
+ printWidth: 100,
13
+ tabWidth: 2,
14
+ useTabs: false,
15
+ bracketSameLine: false,
16
+ arrowParens: "always",
17
+ endOfLine: "lf",
18
+ // Tailwind class sorting — service must install prettier-plugin-tailwindcss separately.
19
+ plugins: [],
20
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "target": "ES2022",
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "moduleResolution": "Bundler",
8
+ "jsx": "react-jsx",
9
+ "strict": true,
10
+ "noUncheckedIndexedAccess": true,
11
+ "noImplicitOverride": true,
12
+ "exactOptionalPropertyTypes": true,
13
+ "noPropertyAccessFromIndexSignature": false,
14
+ "skipLibCheck": true,
15
+ "isolatedModules": true,
16
+ "esModuleInterop": false,
17
+ "allowSyntheticDefaultImports": true,
18
+ "resolveJsonModule": true,
19
+ "forceConsistentCasingInFileNames": true,
20
+ "verbatimModuleSyntax": true
21
+ }
22
+ }
@@ -0,0 +1,26 @@
1
+ // @godxjp/ui — shared Vitest config base.
2
+ //
3
+ // Consume in a service frontend:
4
+ //
5
+ // // vitest.config.ts
6
+ // import base from "@godxjp/ui/vitest-config"
7
+ // import { mergeConfig } from "vitest/config"
8
+ // export default mergeConfig(base, { test: { /* service overrides */ } })
9
+
10
+ import { defineConfig } from "vitest/config"
11
+
12
+ export default defineConfig({
13
+ test: {
14
+ environment: "jsdom",
15
+ globals: false,
16
+ include: ["src/**/*.test.{ts,tsx}"],
17
+ exclude: ["e2e/**", "dist/**", "node_modules/**"],
18
+ coverage: {
19
+ provider: "v8",
20
+ thresholds: {
21
+ statements: 75,
22
+ branches: 70,
23
+ },
24
+ },
25
+ },
26
+ })
@@ -0,0 +1,143 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, HTMLAttributes, ComponentProps } from 'react';
3
+ import { S as SizeProp } from './size-CQwNvOWd.js';
4
+
5
+ type SegmentedControlVariant = "bar" | "pill";
6
+ /** Subset of the shared `SizeProp` — SegmentedControl only ships the
7
+ * two compact-side rungs in practice (no `"large"` design canon yet). */
8
+ type SegmentedControlSize = Exclude<SizeProp, "large">;
9
+ type SegmentedControlOrientation = "horizontal" | "vertical";
10
+ interface SegmentedControlItem<V extends string = string> {
11
+ value: V;
12
+ label: ReactNode;
13
+ icon?: ReactNode;
14
+ disabled?: boolean;
15
+ }
16
+ interface SegmentedControlProps<V extends string = string> extends Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
17
+ items: SegmentedControlItem<V>[];
18
+ value?: V;
19
+ defaultValue?: V;
20
+ onChange?: (next: V) => void;
21
+ variant?: SegmentedControlVariant;
22
+ size?: SegmentedControlSize;
23
+ /** Axis of the radiogroup — controls Arrow-key direction for the
24
+ * roving-tabindex pattern (per WAI-ARIA APG radiogroup). */
25
+ orientation?: SegmentedControlOrientation;
26
+ /** Accessible name for the group — falls back to a generic role label. */
27
+ "aria-label"?: string;
28
+ }
29
+ declare function SegmentedControl<V extends string = string>({ items, value: controlled, defaultValue, onChange, variant, size, orientation, className, ...rest }: SegmentedControlProps<V>): react_jsx_runtime.JSX.Element;
30
+
31
+ /**
32
+ * Locale used by `fmtHour`. Adds the JA suffix style (`9時`) for `ja`
33
+ * and keeps `HH:00` for everything else.
34
+ */
35
+ type TimeLocale = "vi" | "ja" | "en";
36
+ /** Parse "HH:MM" into { h, m }. Tolerates missing minutes. */
37
+ declare function parseHM(value: string): {
38
+ h: number;
39
+ m: number;
40
+ };
41
+ /** Pixel offset for a given clock time within a day-grid column. */
42
+ declare function minToY(h: number, m: number, options: {
43
+ dayStartH: number;
44
+ pxPerMin: number;
45
+ }): number;
46
+ /** Format an hour cell label per locale. */
47
+ declare function fmtHour(h: number, locale: TimeLocale): string;
48
+ /** Default day-grid sizing the WeekView / DayView screens use. */
49
+ declare const DEFAULT_GRID: {
50
+ readonly dayStartH: 6;
51
+ readonly dayEndH: 22;
52
+ readonly pxPerMin: 0.9;
53
+ };
54
+ /**
55
+ * Build a 6×7 Mon-first month grid for (year, monthIdx1to12). Lead-in
56
+ * cells from the previous month and tail cells from the next month are
57
+ * flagged `dim: true`. Shared by MiniMonth + MonthView.
58
+ */
59
+ interface MonthCellRef {
60
+ y: number;
61
+ m: number;
62
+ d: number;
63
+ dim: boolean;
64
+ }
65
+ declare function buildMonthGrid(year: number, month: number): MonthCellRef[];
66
+ /** YYYY-MM-DD key for a {y,m,d} triple. */
67
+ declare function ymd(y: number, m: number, d: number): string;
68
+
69
+ interface CalendarEvent {
70
+ id: string;
71
+ /** Color reference — `CalendarRef.id` whose `color` paints the event. */
72
+ calId: string;
73
+ title: string;
74
+ /** YYYY-MM-DD. */
75
+ date: string;
76
+ allDay?: boolean;
77
+ /** HH:MM (24h). Required when `allDay` is false. */
78
+ start?: string;
79
+ /** HH:MM (24h). Required when `allDay` is false. */
80
+ end?: string;
81
+ attendees: string[];
82
+ /** Free-form status — caller decides which strings are meaningful. */
83
+ status?: string;
84
+ /** Free-form event kind — caller decides. */
85
+ type?: string;
86
+ location?: string;
87
+ note?: string;
88
+ }
89
+ interface CalendarRef {
90
+ id: string;
91
+ name: string;
92
+ color: string;
93
+ shown?: boolean;
94
+ /** Optional grouping bucket used by sidebar lists. */
95
+ group?: string;
96
+ /** True for read-only feeds (e.g. national holidays). */
97
+ readonly?: boolean;
98
+ }
99
+ interface PersonRef {
100
+ id: string;
101
+ name: string;
102
+ /** Short label (2–3 chars) for avatar text. */
103
+ short: string;
104
+ color: string;
105
+ email?: string;
106
+ org?: string;
107
+ role?: string;
108
+ /** Marks the viewer themselves. */
109
+ self?: boolean;
110
+ }
111
+ /**
112
+ * Visual treatment hint for an EventBlock — separated from
113
+ * `CalendarEvent.status` so the primitive stays generic. Consumers map
114
+ * their `type` + `status` into one of these.
115
+ */
116
+ type EventBlockVariant = "solid" | "tint" | "tentative" | "focus";
117
+
118
+ /**
119
+ * MiniMonth — compact 6×7 month grid for sidebars and date pickers.
120
+ * Mon-first, 22px-cell. Renders an event dot when `eventDots[ymd]` is
121
+ * truthy and `--accent-color` for today/selected states.
122
+ */
123
+ interface MiniMonthYMD {
124
+ y: number;
125
+ m: number;
126
+ d: number;
127
+ }
128
+ interface MiniMonthProps extends Omit<ComponentProps<"div">, "onSelect"> {
129
+ /** Year of the grid. */
130
+ year: number;
131
+ /** Month (1–12) of the grid. */
132
+ month: number;
133
+ today: MiniMonthYMD;
134
+ selected?: MiniMonthYMD;
135
+ /** Map of YYYY-MM-DD → has-event boolean. */
136
+ eventDots?: Record<string, boolean>;
137
+ onSelect?: (ymd: MiniMonthYMD) => void;
138
+ /** Day-of-week labels — Mon-first. Default JA single chars. */
139
+ dowLabels?: readonly [string, string, string, string, string, string, string];
140
+ }
141
+ declare function MiniMonth({ year, month, today, selected, eventDots, onSelect, dowLabels, className, ...rest }: MiniMonthProps): react_jsx_runtime.JSX.Element;
142
+
143
+ export { type CalendarEvent as C, DEFAULT_GRID as D, type EventBlockVariant as E, MiniMonth as M, type PersonRef as P, SegmentedControl as S, type TimeLocale as T, type CalendarRef as a, type MiniMonthProps as b, type MiniMonthYMD as c, type MonthCellRef as d, type SegmentedControlItem as e, type SegmentedControlOrientation as f, type SegmentedControlProps as g, type SegmentedControlSize as h, type SegmentedControlVariant as i, buildMonthGrid as j, fmtHour as k, minToY as m, parseHM as p, ymd as y };