@govnepal/ui 0.1.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.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/Alert.d.ts +27 -0
- package/dist/Alert.d.ts.map +1 -0
- package/dist/Alert.js +13 -0
- package/dist/Alert.js.map +1 -0
- package/dist/Badge.d.ts +22 -0
- package/dist/Badge.d.ts.map +1 -0
- package/dist/Badge.js +14 -0
- package/dist/Badge.js.map +1 -0
- package/dist/Button.d.ts +24 -0
- package/dist/Button.d.ts.map +1 -0
- package/dist/Button.js +18 -0
- package/dist/Button.js.map +1 -0
- package/dist/ErrorSummary.d.ts +30 -0
- package/dist/ErrorSummary.d.ts.map +1 -0
- package/dist/ErrorSummary.js +34 -0
- package/dist/ErrorSummary.js.map +1 -0
- package/dist/Header.d.ts +31 -0
- package/dist/Header.d.ts.map +1 -0
- package/dist/Header.js +21 -0
- package/dist/Header.js.map +1 -0
- package/dist/Link.d.ts +20 -0
- package/dist/Link.d.ts.map +1 -0
- package/dist/Link.js +15 -0
- package/dist/Link.js.map +1 -0
- package/dist/TextInput.d.ts +33 -0
- package/dist/TextInput.d.ts.map +1 -0
- package/dist/TextInput.js +16 -0
- package/dist/TextInput.js.map +1 -0
- package/dist/ThemeProvider.d.ts +37 -0
- package/dist/ThemeProvider.d.ts.map +1 -0
- package/dist/ThemeProvider.js +88 -0
- package/dist/ThemeProvider.js.map +1 -0
- package/dist/cx.d.ts +5 -0
- package/dist/cx.d.ts.map +1 -0
- package/dist/cx.js +5 -0
- package/dist/cx.js.map +1 -0
- package/dist/generated/statusTaxonomy.d.ts +11 -0
- package/dist/generated/statusTaxonomy.d.ts.map +1 -0
- package/dist/generated/statusTaxonomy.js +13 -0
- package/dist/generated/statusTaxonomy.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +35 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +19 -0
- package/dist/layout.js.map +1 -0
- package/dist/themeCore.d.ts +41 -0
- package/dist/themeCore.d.ts.map +1 -0
- package/dist/themeCore.js +55 -0
- package/dist/themeCore.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nepal Design System Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# @govnepal/ui
|
|
2
|
+
|
|
3
|
+
The Civic Calm React components — the **behavior** layer. Every component maps to its
|
|
4
|
+
design-guidelines spec id and adds the ARIA, keyboard handling, and focus management that spec
|
|
5
|
+
requires. It contains **no styling of its own**: every visual decision lives in `@govnepal/css`.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
pnpm --filter @govnepal/ui build # generates the taxonomy module, then tsc
|
|
9
|
+
pnpm --filter @govnepal/ui test # behavior tests against the built output, in jsdom
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import "@govnepal/tokens/tokens.css";
|
|
16
|
+
import "@govnepal/css/fonts.css";
|
|
17
|
+
import "@govnepal/css/civic-calm.css";
|
|
18
|
+
import { ThemeProvider, Header, Button } from "@govnepal/ui";
|
|
19
|
+
|
|
20
|
+
export function App() {
|
|
21
|
+
return (
|
|
22
|
+
<ThemeProvider>
|
|
23
|
+
<Header officeNe="गृह मन्त्रालय" officeEn="Ministry of Home Affairs" serviceName="Citizenship" />
|
|
24
|
+
<main id="main">
|
|
25
|
+
<Button variant="primary" type="submit">Submit application</Button>
|
|
26
|
+
</main>
|
|
27
|
+
</ThemeProvider>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`react` and `react-dom` are peer dependencies (18+). Load the three stylesheets once at the root;
|
|
33
|
+
without them the components render unstyled, because the styling is deliberately not in this package.
|
|
34
|
+
|
|
35
|
+
**React Server Components:** every interactive component is marked `"use client"`, so the library
|
|
36
|
+
drops into a Next.js App Router (or any RSC framework) without a wrapper. The server-safe theme
|
|
37
|
+
utilities — `themeInitScript` (to inline in `<head>`) and `applyTheme` — live in a non-client module
|
|
38
|
+
(`themeCore`) and are re-exported, so a Server Component can import them without pulling the client
|
|
39
|
+
provider across the boundary.
|
|
40
|
+
|
|
41
|
+
## Why behavior-only
|
|
42
|
+
|
|
43
|
+
- **`@govnepal/css`** owns colour, spacing, the type scale, all six display modes, print, density
|
|
44
|
+
— the whole visual truth.
|
|
45
|
+
- **`@govnepal/ui`** owns ARIA, keyboard, focus, and state.
|
|
46
|
+
|
|
47
|
+
So a Vue or Web Component port later re-implements behavior only, never a design decision — and a
|
|
48
|
+
plain-HTML site can already use the CSS classes without any of this. What the React layer buys you
|
|
49
|
+
is the wiring that is easy to ship subtly wrong: a `<button>` that is really a button, an error
|
|
50
|
+
summary that actually moves focus, a live region that announces once and not on every navigation.
|
|
51
|
+
|
|
52
|
+
## The ten components
|
|
53
|
+
|
|
54
|
+
| Component | The behavior it adds beyond the CSS class |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `ThemeProvider` / `useTheme` | The §10.2 provider: mode (+ large-text, reduced-motion), language, calendar, density; OS-preference defaults until the user chooses; device persistence; `nested` mode-preview subtrees. |
|
|
57
|
+
| `Container`, `Stack`, `PageSection` | The `as` prop, so a stack can be a `<fieldset>` and a band a labelled `<section>` — semantics pure CSS can't give. |
|
|
58
|
+
| `Button` | Real `<button>`, `type="button"` default (no accidental submit), the loading contract (`aria-busy`, label kept, repeat clicks ignored), `aria-disabled` instead of `disabled` so it stays reachable. |
|
|
59
|
+
| `Link` | The accessible-name half of the external `↗` / download `↓` markers, so the marker never ships without spoken text; hardened `rel` for external links. |
|
|
60
|
+
| `TextInput` | Label binding, `aria-describedby` joining hint then error, `aria-invalid` only on error, a stable id the error summary can target. |
|
|
61
|
+
| `ErrorSummary` | Focus moves to it on appearance; each entry moves focus **into** its field, not just scrolls near it; built from the same validation result as the inline errors. |
|
|
62
|
+
| `Alert` | The live-region contract — dynamic alerts announce (assertive for error/emergency), static ones don't; the emergency variant is never given a citizen dismiss. |
|
|
63
|
+
| `Badge` | Renders one status from the generated taxonomy; a status outside `data/status-taxonomy.yaml` is a TypeScript error, not a runtime surprise. |
|
|
64
|
+
| `Header` | Banner role, skip link first, text language switcher, and the emblem handled as a required asset — see below. |
|
|
65
|
+
|
|
66
|
+
## Generated, not hand-typed
|
|
67
|
+
|
|
68
|
+
`Badge` renders status labels **verbatim** from `data/status-taxonomy.yaml`. Retyping the eight
|
|
69
|
+
bilingual labels here would be the "locally invented synonym" the glossary rules forbid, so
|
|
70
|
+
`build/generate.mjs` emits `src/generated/statusTaxonomy.ts` from the guidelines before every
|
|
71
|
+
build. `StatusId` is a union of the real ids; the taxonomy is the single source.
|
|
72
|
+
|
|
73
|
+
## The emblem gap
|
|
74
|
+
|
|
75
|
+
`Header` takes the emblem as a **prop** and never draws it — recreating, recolouring, or tracing
|
|
76
|
+
the coat of arms is prohibited (identity/emblem), and `design-assets/emblems/files/` is currently
|
|
77
|
+
empty. With no `emblem` passed, it renders an explicit, labelled "asset missing" placeholder for
|
|
78
|
+
development; a test asserts the placeholder contains no `<img>` or `<svg>`, so invented artwork
|
|
79
|
+
can't slip in. The real emblem drops in as a prop the moment the master exists.
|
package/dist/Alert.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Alert (components/alert.md) — page-level status the user must read.
|
|
4
|
+
*
|
|
5
|
+
* The behavior this layer adds over the .gov-alert classes is the live-region contract, which is
|
|
6
|
+
* easy to get subtly wrong:
|
|
7
|
+
* - an alert that appears DYNAMICALLY (a failed submit, a just-arrived outage notice) is
|
|
8
|
+
* announced, so `live` opts it into role="alert"/aria-live;
|
|
9
|
+
* - a STATIC alert already on the page at load is ordinary content and must NOT be a live
|
|
10
|
+
* region, or a screen reader re-announces it on every navigation;
|
|
11
|
+
* - the emergency variant is never given a close button here, because it is not dismissible by
|
|
12
|
+
* the citizen (§7.4) — only the authorized office removes it.
|
|
13
|
+
*/
|
|
14
|
+
type AlertVariant = "info" | "success" | "warning" | "error" | "emergency";
|
|
15
|
+
interface AlertProps {
|
|
16
|
+
variant: AlertVariant;
|
|
17
|
+
title: ReactNode;
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
/** Set when the alert appears dynamically, so assistive tech announces it. */
|
|
20
|
+
live?: boolean;
|
|
21
|
+
/** The status icon (icon.size.md). Decorative — title + colour + this together carry state. */
|
|
22
|
+
icon?: ReactNode;
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function Alert({ variant, title, children, live, icon, className }: AlertProps): import("react").JSX.Element;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=Alert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../src/Alert.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC;;;;;;;;;;;GAWG;AAEH,KAAK,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;AAE3E,UAAU,UAAU;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+FAA+F;IAC/F,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAY,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,UAAU,+BAqB5F"}
|
package/dist/Alert.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cx } from "./cx.js";
|
|
4
|
+
export function Alert({ variant, title, children, live = false, icon, className }) {
|
|
5
|
+
// error and emergency are assertive (interrupt); info/success/warning are polite. A static
|
|
6
|
+
// alert gets no live role at all.
|
|
7
|
+
const assertive = variant === "error" || variant === "emergency";
|
|
8
|
+
const liveProps = live
|
|
9
|
+
? { role: "alert", "aria-live": assertive ? "assertive" : "polite" }
|
|
10
|
+
: {};
|
|
11
|
+
return (_jsxs("div", { className: cx("gov-alert", `gov-alert--${variant}`, className), ...liveProps, children: [icon && (_jsx("span", { className: "gov-alert__icon", "aria-hidden": "true", children: icon })), _jsxs("div", { className: "gov-alert__body", children: [_jsx("span", { className: "gov-alert__title", children: title }), children && _jsx("div", { children: children })] })] }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=Alert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.js","sourceRoot":"","sources":["../src/Alert.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AA4B7B,MAAM,UAAU,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,KAAK,EAAE,IAAI,EAAE,SAAS,EAAc;IAC3F,2FAA2F;IAC3F,kCAAkC;IAClC,MAAM,SAAS,GAAG,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,WAAW,CAAC;IACjE,MAAM,SAAS,GAAG,IAAI;QACpB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,CAAE,WAAqB,CAAC,CAAC,CAAE,QAAkB,EAAE;QACnG,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,cAAc,OAAO,EAAE,EAAE,SAAS,CAAC,KAAM,SAAS,aAC/E,IAAI,IAAI,CACP,eAAM,SAAS,EAAC,iBAAiB,iBAAa,MAAM,YACjD,IAAI,GACA,CACR,EACD,eAAK,SAAS,EAAC,iBAAiB,aAC9B,eAAM,SAAS,EAAC,kBAAkB,YAAE,KAAK,GAAQ,EAChD,QAAQ,IAAI,wBAAM,QAAQ,GAAO,IAC9B,IACF,CACP,CAAC;AACJ,CAAC"}
|
package/dist/Badge.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { STATUS_TAXONOMY, type StatusId } from "./generated/statusTaxonomy.js";
|
|
3
|
+
/**
|
|
4
|
+
* Status badge (components/badge.md) — renders one status from the official taxonomy (§7.3.2) and
|
|
5
|
+
* nothing else. There is no free-text badge: an ad-hoc status is not a styling problem, it means
|
|
6
|
+
* the taxonomy needs extending first. So this takes a `status` id, not a label and colour — the
|
|
7
|
+
* label, the bilingual text, and the colour variant all come from the generated taxonomy, which
|
|
8
|
+
* is generated from the guidelines. A status not in the taxonomy is a TypeScript error.
|
|
9
|
+
*
|
|
10
|
+
* The badge carries text + icon + colour, never colour alone (§4.1). It is never interactive —
|
|
11
|
+
* filtering happens in the filter bar — so it is a <span>, not a button.
|
|
12
|
+
*/
|
|
13
|
+
interface BadgeProps {
|
|
14
|
+
status: StatusId;
|
|
15
|
+
/** An optional status icon (icon.size.sm). Decorative — the label already carries the meaning. */
|
|
16
|
+
icon?: ReactNode;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function Badge({ status, icon, className }: BadgeProps): import("react").JSX.Element;
|
|
20
|
+
/** Re-exported so an officer worklist can drive its own logic from the same taxonomy. */
|
|
21
|
+
export { STATUS_TAXONOMY, type StatusId };
|
|
22
|
+
//# sourceMappingURL=Badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../src/Badge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE/E;;;;;;;;;GASG;AAEH,UAAU,UAAU;IAClB,MAAM,EAAE,QAAQ,CAAC;IACjB,kGAAkG;IAClG,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,UAAU,+BAe5D;AAED,yFAAyF;AACzF,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,CAAC"}
|
package/dist/Badge.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cx } from "./cx.js";
|
|
4
|
+
import { useTheme } from "./ThemeProvider.js";
|
|
5
|
+
import { STATUS_TAXONOMY } from "./generated/statusTaxonomy.js";
|
|
6
|
+
export function Badge({ status, icon, className }) {
|
|
7
|
+
const { language } = useTheme();
|
|
8
|
+
const entry = STATUS_TAXONOMY[status];
|
|
9
|
+
const label = language === "ne" ? entry.label_ne : entry.label;
|
|
10
|
+
return (_jsxs("span", { className: cx("gov-badge", `gov-badge--${entry.badge}`, className), children: [icon && (_jsx("span", { className: "gov-badge__icon", "aria-hidden": "true", children: icon })), label] }));
|
|
11
|
+
}
|
|
12
|
+
/** Re-exported so an officer worklist can drive its own logic from the same taxonomy. */
|
|
13
|
+
export { STATUS_TAXONOMY };
|
|
14
|
+
//# sourceMappingURL=Badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.js","sourceRoot":"","sources":["../src/Badge.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAiB,MAAM,+BAA+B,CAAC;AAoB/E,MAAM,UAAU,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAc;IAC3D,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;IAE/D,OAAO,CACL,gBAAM,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,cAAc,KAAK,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,aACrE,IAAI,IAAI,CACP,eAAM,SAAS,EAAC,iBAAiB,iBAAa,MAAM,YACjD,IAAI,GACA,CACR,EACA,KAAK,IACD,CACR,CAAC;AACJ,CAAC;AAED,yFAAyF;AACzF,OAAO,EAAE,eAAe,EAAiB,CAAC"}
|
package/dist/Button.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Button (components/button.md) — for actions that change state (submit, save, approve). If it
|
|
4
|
+
* only takes the user somewhere, it is a Link, not a Button.
|
|
5
|
+
*
|
|
6
|
+
* The behavior this layer adds over the .gov-button classes:
|
|
7
|
+
* - a real <button> always (never a styled div), so Enter and Space both activate for free;
|
|
8
|
+
* - the loading contract: aria-busy, a label that stays put, and repeat activation ignored
|
|
9
|
+
* while busy, rather than the control vanishing from the tab order;
|
|
10
|
+
* - disabled via aria-disabled, keeping the control focusable so "why is this disabled" can be
|
|
11
|
+
* discovered — an invisible disabled control is a support-call generator (the spec's words).
|
|
12
|
+
*/
|
|
13
|
+
interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "disabled"> {
|
|
14
|
+
variant?: "primary" | "secondary" | "destructive";
|
|
15
|
+
size?: "sm" | "md" | "lg";
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
loadingLabel?: ReactNode;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
icon?: ReactNode;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
}
|
|
22
|
+
export declare function Button({ variant, size, loading, loadingLabel, disabled, icon, className, children, onClick, type, ...rest }: ButtonProps): import("react").JSX.Element;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=Button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../src/Button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG7D;;;;;;;;;;GAUG;AAEH,UAAU,WAAY,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IACrF,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;IAClD,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,MAAM,CAAC,EACrB,OAAmB,EACnB,IAAW,EACX,OAAe,EACf,YAAY,EACZ,QAAgB,EAChB,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,OAAO,EACP,IAAe,EACf,GAAG,IAAI,EACR,EAAE,WAAW,+BAwCb"}
|
package/dist/Button.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cx } from "./cx.js";
|
|
4
|
+
export function Button({ variant = "primary", size = "md", loading = false, loadingLabel, disabled = false, icon, className, children, onClick, type = "button", ...rest }) {
|
|
5
|
+
const inert = disabled || loading;
|
|
6
|
+
return (_jsx("button", {
|
|
7
|
+
// type defaults to "button": an un-typed button inside a form submits it, which is a
|
|
8
|
+
// classic accidental-submit bug. A submit button opts in explicitly with type="submit".
|
|
9
|
+
type: type, className: cx("gov-button", `gov-button--${variant}`, size !== "md" && `gov-button--${size}`, className), "aria-disabled": inert || undefined, "aria-busy": loading || undefined, onClick: (event) => {
|
|
10
|
+
// Repeat activation is ignored while busy or disabled — without removing the control.
|
|
11
|
+
if (inert) {
|
|
12
|
+
event.preventDefault();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
onClick?.(event);
|
|
16
|
+
}, ...rest, children: loading ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "gov-button__spinner", "aria-hidden": "true" }), _jsx("span", { children: loadingLabel ?? children })] })) : (_jsxs(_Fragment, { children: [icon && (_jsx("span", { className: "gov-button__icon", "aria-hidden": "true", children: icon })), _jsx("span", { children: children })] })) }));
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=Button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../src/Button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAwB7B,MAAM,UAAU,MAAM,CAAC,EACrB,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,IAAI,EACX,OAAO,GAAG,KAAK,EACf,YAAY,EACZ,QAAQ,GAAG,KAAK,EAChB,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,OAAO,EACP,IAAI,GAAG,QAAQ,EACf,GAAG,IAAI,EACK;IACZ,MAAM,KAAK,GAAG,QAAQ,IAAI,OAAO,CAAC;IAClC,OAAO,CACL;QACE,qFAAqF;QACrF,wFAAwF;QACxF,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CAAC,YAAY,EAAE,eAAe,OAAO,EAAE,EAAE,IAAI,KAAK,IAAI,IAAI,eAAe,IAAI,EAAE,EAAE,SAAS,CAAC,mBAGzF,KAAK,IAAI,SAAS,eACtB,OAAO,IAAI,SAAS,EAC/B,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,sFAAsF;YACtF,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,OAAO;YACT,CAAC;YACD,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,KACG,IAAI,YAEP,OAAO,CAAC,CAAC,CAAC,CACT,8BACE,eAAM,SAAS,EAAC,qBAAqB,iBAAa,MAAM,GAAG,EAE3D,yBAAO,YAAY,IAAI,QAAQ,GAAQ,IACtC,CACJ,CAAC,CAAC,CAAC,CACF,8BACG,IAAI,IAAI,CACP,eAAM,SAAS,EAAC,kBAAkB,iBAAa,MAAM,YAClD,IAAI,GACA,CACR,EACD,yBAAO,QAAQ,GAAQ,IACtB,CACJ,GACM,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error summary (components/error-summary.md) — after a failed submit, every problem in one box
|
|
3
|
+
* at the top, each linked to its field. Mandatory on every form alongside inline errors (§7.1).
|
|
4
|
+
*
|
|
5
|
+
* Two behaviors are the whole reason this is a component and not a styled list:
|
|
6
|
+
* 1. On appearance it takes focus (tabindex=-1 + focus()), so a keyboard or screen-reader user
|
|
7
|
+
* is put at the summary the instant the submit fails, not left wherever they were.
|
|
8
|
+
* 2. Each entry does not merely SCROLL to its field — it moves FOCUS into it. A plain #anchor
|
|
9
|
+
* scrolls the field into view but often leaves focus behind, so a keyboard user arrives
|
|
10
|
+
* next to the field and has to hunt for it. This intercepts the click and focuses the target.
|
|
11
|
+
*
|
|
12
|
+
* The entries are built from the SAME validation result that renders the inline errors — one
|
|
13
|
+
* source, two renderings, so the summary and the field can never disagree (§7.1). The caller
|
|
14
|
+
* passes that shared result in; this component does not re-derive errors.
|
|
15
|
+
*/
|
|
16
|
+
export interface FieldError {
|
|
17
|
+
/** The id of the input this error belongs to — the link target. */
|
|
18
|
+
fieldId: string;
|
|
19
|
+
/** The message, identical to the inline error text ("Enter your mobile number"). */
|
|
20
|
+
message: string;
|
|
21
|
+
}
|
|
22
|
+
interface ErrorSummaryProps {
|
|
23
|
+
errors: FieldError[];
|
|
24
|
+
/** Move focus here when the summary appears. On by default — a summary appears only on failure. */
|
|
25
|
+
focusOnAppear?: boolean;
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function ErrorSummary({ errors, focusOnAppear, className }: ErrorSummaryProps): import("react").JSX.Element | null;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=ErrorSummary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorSummary.d.ts","sourceRoot":"","sources":["../src/ErrorSummary.tsx"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,iBAAiB;IACzB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,mGAAmG;IACnG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,aAAoB,EAAE,SAAS,EAAE,EAAE,iBAAiB,sCAwD1F"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useId, useRef } from "react";
|
|
4
|
+
import { cx } from "./cx.js";
|
|
5
|
+
import { useTheme } from "./ThemeProvider.js";
|
|
6
|
+
const HEADING = { ne: "समस्या छ", en: "There is a problem" };
|
|
7
|
+
export function ErrorSummary({ errors, focusOnAppear = true, className }) {
|
|
8
|
+
const { language } = useTheme();
|
|
9
|
+
const ref = useRef(null);
|
|
10
|
+
const titleId = useId();
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (focusOnAppear && errors.length > 0)
|
|
13
|
+
ref.current?.focus();
|
|
14
|
+
// Re-focus whenever the set of errors changes — a second failed submit is a new event the
|
|
15
|
+
// user needs taking back to the top.
|
|
16
|
+
}, [focusOnAppear, errors]);
|
|
17
|
+
if (errors.length === 0)
|
|
18
|
+
return null;
|
|
19
|
+
const focusField = (fieldId) => (event) => {
|
|
20
|
+
const field = document.getElementById(fieldId);
|
|
21
|
+
if (!field)
|
|
22
|
+
return; // Fall back to the native #anchor jump.
|
|
23
|
+
event.preventDefault();
|
|
24
|
+
field.focus();
|
|
25
|
+
// Focus alone is what matters for accessibility; scrolling is a nicety. Guard it because not
|
|
26
|
+
// every environment implements it (jsdom, some embedded webviews).
|
|
27
|
+
field.scrollIntoView?.({ block: "center", behavior: "auto" });
|
|
28
|
+
};
|
|
29
|
+
return (_jsxs("div", { ref: ref, className: cx("gov-error-summary", className),
|
|
30
|
+
// role="alert" announces it on appearance; tabindex=-1 makes it programmatically focusable
|
|
31
|
+
// without adding it to the normal tab order.
|
|
32
|
+
role: "alert", tabIndex: -1, "aria-labelledby": titleId, children: [_jsxs("h2", { className: "gov-error-summary__title", id: titleId, children: [HEADING[language], _jsxs("span", { className: "gov-visually-hidden", children: [" ", "(", errors.length, ")"] })] }), _jsx("ul", { className: "gov-error-summary__list", children: errors.map((error) => (_jsx("li", { children: _jsx("a", { className: "gov-error-summary__link", href: `#${error.fieldId}`, onClick: focusField(error.fieldId), children: error.message }) }, error.fieldId))) })] }));
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=ErrorSummary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorSummary.js","sourceRoot":"","sources":["../src/ErrorSummary.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAgC9C,MAAM,OAAO,GAAG,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,oBAAoB,EAAW,CAAC;AAEtE,MAAM,UAAU,YAAY,CAAC,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,EAAE,SAAS,EAAqB;IACzF,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IAExB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,aAAa,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QAC7D,0FAA0F;QAC1F,qCAAqC;IACvC,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;IAE5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAErC,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,CAAC,KAAuB,EAAE,EAAE;QAClE,MAAM,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,wCAAwC;QAC5D,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,6FAA6F;QAC7F,mEAAmE;QACnE,KAAK,CAAC,cAAc,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC;IAEF,OAAO,CACL,eACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CAAC,mBAAmB,EAAE,SAAS,CAAC;QAC7C,2FAA2F;QAC3F,6CAA6C;QAC7C,IAAI,EAAC,OAAO,EACZ,QAAQ,EAAE,CAAC,CAAC,qBACK,OAAO,aAExB,cAAI,SAAS,EAAC,0BAA0B,EAAC,EAAE,EAAE,OAAO,aACjD,OAAO,CAAC,QAAQ,CAAC,EAElB,gBAAM,SAAS,EAAC,qBAAqB,aAClC,GAAG,OACF,MAAM,CAAC,MAAM,SACV,IACJ,EACL,aAAI,SAAS,EAAC,yBAAyB,YACpC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACrB,uBACE,YACE,SAAS,EAAC,yBAAyB,EACnC,IAAI,EAAE,IAAI,KAAK,CAAC,OAAO,EAAE,EACzB,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,YAEjC,KAAK,CAAC,OAAO,GACZ,IAPG,KAAK,CAAC,OAAO,CAQjB,CACN,CAAC,GACC,IACD,CACP,CAAC;AACJ,CAAC"}
|
package/dist/Header.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { type Language } from "./ThemeProvider.js";
|
|
3
|
+
/**
|
|
4
|
+
* Government header (components/header.md, identity/government-header) — on every page of every
|
|
5
|
+
* service, structurally identical everywhere. There is no per-ministry variant: consistency is
|
|
6
|
+
* the citizen's primary cue that a site is genuinely governmental (§9.2), so the only inputs are
|
|
7
|
+
* the office lockup and the service name.
|
|
8
|
+
*
|
|
9
|
+
* The emblem is a REQUIRED asset, taken as a prop. This component never draws it — recreating,
|
|
10
|
+
* recolouring, or tracing the coat of arms is prohibited (identity/emblem), and no verified
|
|
11
|
+
* master exists in design-assets yet. When `emblem` is omitted, it renders an explicit, ugly
|
|
12
|
+
* dev-only placeholder rather than inventing artwork that might look shippable.
|
|
13
|
+
*/
|
|
14
|
+
interface HeaderProps {
|
|
15
|
+
/** The verified emblem, e.g. <img src={emblemUrl} alt="…" /> from design-assets. Required in prod. */
|
|
16
|
+
emblem?: ReactNode;
|
|
17
|
+
/** Office name, Nepali first then English (Article 7). Both are shown; en hides on mobile. */
|
|
18
|
+
officeNe: string;
|
|
19
|
+
officeEn: string;
|
|
20
|
+
/** The citizen-facing service name, not an internal system name. */
|
|
21
|
+
serviceName?: ReactNode;
|
|
22
|
+
/** Where the language switcher points for each language. Defaults to no-op anchors. */
|
|
23
|
+
languageHrefs?: Record<Language, string>;
|
|
24
|
+
/** The skip-link target id — the header renders the skip link as the first focusable element. */
|
|
25
|
+
skipTargetId?: string;
|
|
26
|
+
children?: ReactNode;
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function Header({ emblem, officeNe, officeEn, serviceName, languageHrefs, skipTargetId, children, className, }: HeaderProps): import("react").JSX.Element;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=Header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../src/Header.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;;;;;;;;;GAUG;AAEH,UAAU,WAAW;IACnB,sGAAsG;IACtG,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACzC,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,aAAa,EACb,YAAqB,EACrB,QAAQ,EACR,SAAS,GACV,EAAE,WAAW,+BA0Eb"}
|
package/dist/Header.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cx } from "./cx.js";
|
|
4
|
+
import { useTheme } from "./ThemeProvider.js";
|
|
5
|
+
const SKIP_LABEL = { ne: "मुख्य सामग्रीमा जानुहोस्", en: "Skip to main content" };
|
|
6
|
+
const EMBLEM_ALT = { ne: "नेपाल सरकारको निशान छाप", en: "Emblem of the Government of Nepal" };
|
|
7
|
+
export function Header({ emblem, officeNe, officeEn, serviceName, languageHrefs, skipTargetId = "main", children, className, }) {
|
|
8
|
+
const { language, setLanguage } = useTheme();
|
|
9
|
+
return (_jsxs("header", { className: cx("gov-header", className), role: "banner", children: [_jsx("a", { className: "gov-skip-link", href: `#${skipTargetId}`, children: SKIP_LABEL[language] }), _jsx("div", { className: "gov-container", children: _jsxs("div", { className: "gov-header__inner", children: [_jsxs("span", { className: "gov-header__lockup", children: [emblem ? (_jsx("span", { className: "gov-header__emblem", role: "img", "aria-label": EMBLEM_ALT[language], children: emblem })) : (
|
|
10
|
+
// Dev-only. The real emblem is a verified master from design-assets; none exists yet.
|
|
11
|
+
_jsx("span", { className: "gov-header__emblem-missing", role: "img", "aria-label": `${EMBLEM_ALT[language]} — asset missing`, title: "Emblem master not yet available in design-assets/emblems", children: "\u0928\u093F\u0936\u093E\u0928" })), _jsxs("span", { className: "gov-header__office", children: [_jsx("span", { className: "gov-header__office-ne", lang: "ne", children: officeNe }), _jsx("span", { className: "gov-header__office-en", lang: "en", children: officeEn })] })] }), serviceName && _jsx("span", { className: "gov-header__service", children: serviceName }), _jsxs("nav", { className: "gov-header__language", "aria-label": language === "ne" ? "भाषा" : "Language", children: [_jsx("a", { href: languageHrefs?.ne ?? "#", lang: "ne", hrefLang: "ne", "aria-current": language === "ne" ? "true" : undefined, onClick: (event) => {
|
|
12
|
+
if (!languageHrefs)
|
|
13
|
+
event.preventDefault();
|
|
14
|
+
setLanguage("ne");
|
|
15
|
+
}, children: "\u0928\u0947\u092A\u093E\u0932\u0940" }), _jsx("span", { "aria-hidden": "true", children: "/" }), _jsx("a", { href: languageHrefs?.en ?? "#", lang: "en", hrefLang: "en", "aria-current": language === "en" ? "true" : undefined, onClick: (event) => {
|
|
16
|
+
if (!languageHrefs)
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
setLanguage("en");
|
|
19
|
+
}, children: "EN" })] }), children] }) })] }));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=Header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../src/Header.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAiB,MAAM,oBAAoB,CAAC;AA8B7D,MAAM,UAAU,GAAG,EAAE,EAAE,EAAE,0BAA0B,EAAE,EAAE,EAAE,sBAAsB,EAAW,CAAC;AAC3F,MAAM,UAAU,GAAG,EAAE,EAAE,EAAE,yBAAyB,EAAE,EAAE,EAAE,mCAAmC,EAAW,CAAC;AAEvG,MAAM,UAAU,MAAM,CAAC,EACrB,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,aAAa,EACb,YAAY,GAAG,MAAM,EACrB,QAAQ,EACR,SAAS,GACG;IACZ,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,QAAQ,EAAE,CAAC;IAE7C,OAAO,CACL,kBAAQ,SAAS,EAAE,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC,EAAE,IAAI,EAAC,QAAQ,aAE3D,YAAG,SAAS,EAAC,eAAe,EAAC,IAAI,EAAE,IAAI,YAAY,EAAE,YAClD,UAAU,CAAC,QAAQ,CAAC,GACnB,EACJ,cAAK,SAAS,EAAC,eAAe,YAC5B,eAAK,SAAS,EAAC,mBAAmB,aAChC,gBAAM,SAAS,EAAC,oBAAoB,aACjC,MAAM,CAAC,CAAC,CAAC,CACR,eAAM,SAAS,EAAC,oBAAoB,EAAC,IAAI,EAAC,KAAK,gBAAa,UAAU,CAAC,QAAQ,CAAC,YAC7E,MAAM,GACF,CACR,CAAC,CAAC,CAAC;gCACF,sFAAsF;gCACtF,eACE,SAAS,EAAC,4BAA4B,EACtC,IAAI,EAAC,KAAK,gBACE,GAAG,UAAU,CAAC,QAAQ,CAAC,kBAAkB,EACrD,KAAK,EAAC,0DAA0D,+CAG3D,CACR,EACD,gBAAM,SAAS,EAAC,oBAAoB,aAClC,eAAM,SAAS,EAAC,uBAAuB,EAAC,IAAI,EAAC,IAAI,YAC9C,QAAQ,GACJ,EACP,eAAM,SAAS,EAAC,uBAAuB,EAAC,IAAI,EAAC,IAAI,YAC9C,QAAQ,GACJ,IACF,IACF,EAEN,WAAW,IAAI,eAAM,SAAS,EAAC,qBAAqB,YAAE,WAAW,GAAQ,EAI1E,eAAK,SAAS,EAAC,sBAAsB,gBAAa,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,aACvF,YACE,IAAI,EAAE,aAAa,EAAE,EAAE,IAAI,GAAG,EAC9B,IAAI,EAAC,IAAI,EACT,QAAQ,EAAC,IAAI,kBACC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACpD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;wCACjB,IAAI,CAAC,aAAa;4CAAE,KAAK,CAAC,cAAc,EAAE,CAAC;wCAC3C,WAAW,CAAC,IAAI,CAAC,CAAC;oCACpB,CAAC,qDAGC,EACJ,8BAAkB,MAAM,kBAAS,EACjC,YACE,IAAI,EAAE,aAAa,EAAE,EAAE,IAAI,GAAG,EAC9B,IAAI,EAAC,IAAI,EACT,QAAQ,EAAC,IAAI,kBACC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACpD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;wCACjB,IAAI,CAAC,aAAa;4CAAE,KAAK,CAAC,cAAc,EAAE,CAAC;wCAC3C,WAAW,CAAC,IAAI,CAAC,CAAC;oCACpB,CAAC,mBAGC,IACA,EAEL,QAAQ,IACL,GACF,IACC,CACV,CAAC;AACJ,CAAC"}
|
package/dist/Link.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Link (components/link.md) — for navigation. Anything that changes state is a Button.
|
|
4
|
+
*
|
|
5
|
+
* The behavior this layer adds over the .gov-link classes is the accessible-name half of the
|
|
6
|
+
* visual markers: an external link's ↗ and a download link's ↓ are decorative (aria-hidden in
|
|
7
|
+
* CSS), so the fact that the link leaves .gov.np, or points at a file, must be carried in text a
|
|
8
|
+
* screen reader can read. This component appends that text, bilingually, so a developer cannot
|
|
9
|
+
* ship the visual marker without its accessible counterpart — the exact gap §9.2 and §4.1 warn
|
|
10
|
+
* about.
|
|
11
|
+
*/
|
|
12
|
+
interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
13
|
+
variant?: "default" | "external" | "download" | "back";
|
|
14
|
+
/** Standalone links (not inline in a paragraph) take the 44px min hit area (components/link.md). */
|
|
15
|
+
standalone?: boolean;
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export declare function Link({ variant, standalone, className, children, href, ...rest }: LinkProps): import("react").JSX.Element;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=Link.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../src/Link.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAI7D;;;;;;;;;GASG;AAEH,UAAU,SAAU,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IACjE,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;IACvD,oGAAoG;IACpG,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAID,wBAAgB,IAAI,CAAC,EAAE,OAAmB,EAAE,UAAkB,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,+BAgC9G"}
|
package/dist/Link.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cx } from "./cx.js";
|
|
4
|
+
import { useTheme } from "./ThemeProvider.js";
|
|
5
|
+
const EXTERNAL_NOTE = { ne: "(बाह्य साइट)", en: "(external site)" };
|
|
6
|
+
export function Link({ variant = "default", standalone = false, className, children, href, ...rest }) {
|
|
7
|
+
const { language } = useTheme();
|
|
8
|
+
const isExternal = variant === "external";
|
|
9
|
+
const isDownload = variant === "download";
|
|
10
|
+
return (_jsxs("a", { href: href, className: cx("gov-link", variant !== "default" && `gov-link--${variant}`, standalone && "gov-link--standalone", className), ...(isExternal ? { rel: "noopener noreferrer" } : {}), ...rest, children: [children, isExternal && _jsxs("span", { className: "gov-visually-hidden", children: [" ", EXTERNAL_NOTE[language]] }), isDownload && rest["aria-label"] === undefined && (
|
|
11
|
+
// A download link should state format and size in its own text ("Form (PDF, 240 KB)");
|
|
12
|
+
// this is only a fallback marker, not a substitute for that content.
|
|
13
|
+
_jsxs("span", { className: "gov-visually-hidden", children: [" ", language === "ne" ? "(डाउनलोड)" : "(download)"] }))] }));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=Link.js.map
|
package/dist/Link.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Link.js","sourceRoot":"","sources":["../src/Link.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAoB9C,MAAM,aAAa,GAAG,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,iBAAiB,EAAW,CAAC;AAE7E,MAAM,UAAU,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,UAAU,GAAG,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,EAAa;IAC7G,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAAC;IAEhC,MAAM,UAAU,GAAG,OAAO,KAAK,UAAU,CAAC;IAC1C,MAAM,UAAU,GAAG,OAAO,KAAK,UAAU,CAAC;IAE1C,OAAO,CACL,aACE,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CACX,UAAU,EACV,OAAO,KAAK,SAAS,IAAI,aAAa,OAAO,EAAE,EAC/C,UAAU,IAAI,sBAAsB,EACpC,SAAS,CACV,KAIG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAClD,IAAI,aAEP,QAAQ,EAGR,UAAU,IAAI,gBAAM,SAAS,EAAC,qBAAqB,kBAAG,aAAa,CAAC,QAAQ,CAAC,IAAQ,EACrF,UAAU,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,SAAS,IAAI;YACjD,uFAAuF;YACvF,qEAAqE;YACrE,gBAAM,SAAS,EAAC,qBAAqB,kBAAG,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,IAAQ,CAC/F,IACC,CACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type InputHTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Text input (components/text-input.md) — one question per row (§7.1).
|
|
4
|
+
*
|
|
5
|
+
* Almost the entire value of this component is the accessibility wiring, which is fiddly and
|
|
6
|
+
* therefore the thing most often shipped wrong:
|
|
7
|
+
* - a visible <label for> bound to the input (never a placeholder acting as the label);
|
|
8
|
+
* - helper text and error text joined into aria-describedby in the right order;
|
|
9
|
+
* - aria-invalid on error, with the error message announced;
|
|
10
|
+
* - the value is NEVER cleared on error (§7.1) — this component is controlled/uncontrolled by
|
|
11
|
+
* the caller and never resets it;
|
|
12
|
+
* - a STABLE id, because the error summary links to it (components/error-summary.md).
|
|
13
|
+
*
|
|
14
|
+
* A width HINT (widthChars) is offered because a full-width box for a 2-digit ward number tells
|
|
15
|
+
* the citizen the wrong thing about what to type (components/text-input.md's Anatomy).
|
|
16
|
+
*/
|
|
17
|
+
interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "id" | "prefix" | "suffix"> {
|
|
18
|
+
/** The question itself, in sentence case ("Citizenship number"). Always visible, always present. */
|
|
19
|
+
label: ReactNode;
|
|
20
|
+
/** Stable id — the error summary links to it. Auto-generated if omitted, but pass one for forms. */
|
|
21
|
+
id?: string;
|
|
22
|
+
/** Format example for hard fields ("e.g. 12-01-76-12345"). Bound via aria-describedby. */
|
|
23
|
+
hint?: ReactNode;
|
|
24
|
+
/** The error message. Specific and actionable ("Enter your mobile number"), never "Invalid". */
|
|
25
|
+
error?: ReactNode;
|
|
26
|
+
/** Width hint in characters — the input sizes to the content, not the container. */
|
|
27
|
+
widthChars?: 2 | 4 | 10 | 20;
|
|
28
|
+
prefix?: ReactNode;
|
|
29
|
+
suffix?: ReactNode;
|
|
30
|
+
}
|
|
31
|
+
export declare function TextInput({ label, id, hint, error, widthChars, prefix, suffix, className, ...rest }: TextInputProps): import("react").JSX.Element;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=TextInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../src/TextInput.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAS,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGxE;;;;;;;;;;;;;;GAcG;AAIH,UAAU,cAAe,SAAQ,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,IAAI,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACtG,oGAAoG;IACpG,KAAK,EAAE,SAAS,CAAC;IACjB,oGAAoG;IACpG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0FAA0F;IAC1F,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gGAAgG;IAChG,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,oFAAoF;IACpF,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,EAAE,EACF,IAAI,EACJ,KAAK,EACL,UAAU,EACV,MAAM,EACN,MAAM,EACN,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,+BAkDhB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { cx } from "./cx.js";
|
|
5
|
+
export function TextInput({ label, id, hint, error, widthChars, prefix, suffix, className, ...rest }) {
|
|
6
|
+
const generatedId = useId();
|
|
7
|
+
const inputId = id ?? generatedId;
|
|
8
|
+
const hintId = `${inputId}-hint`;
|
|
9
|
+
const errorId = `${inputId}-error`;
|
|
10
|
+
// Order matters: the hint is announced before the error, matching reading order.
|
|
11
|
+
const describedBy = [hint ? hintId : null, error ? errorId : null].filter(Boolean).join(" ") || undefined;
|
|
12
|
+
const widthClass = widthChars ? `gov-input--width-${widthChars}` : undefined;
|
|
13
|
+
const input = (_jsx("input", { id: inputId, className: cx("gov-input", widthClass, !prefix && !suffix && className), "aria-describedby": describedBy, "aria-invalid": error ? true : undefined, ...rest }));
|
|
14
|
+
return (_jsxs("div", { className: cx("gov-field", error ? "gov-field--error" : undefined), children: [_jsx("label", { className: "gov-field__label", htmlFor: inputId, children: label }), hint && (_jsx("span", { className: "gov-field__hint", id: hintId, children: hint })), prefix || suffix ? (_jsxs("span", { className: cx("gov-input-group", className), children: [prefix && _jsx("span", { className: "gov-input-group__affix", children: prefix }), input, suffix && _jsx("span", { className: "gov-input-group__affix", children: suffix })] })) : (input), error && (_jsxs("span", { className: "gov-field__error", id: errorId, children: [_jsx("svg", { className: "gov-field__error-icon", viewBox: "0 0 24 24", "aria-hidden": "true", fill: "currentColor", children: _jsx("path", { d: "M12 2a10 10 0 100 20 10 10 0 000-20zm-1 5h2v6h-2V7zm0 8h2v2h-2v-2z" }) }), error] }))] }));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=TextInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextInput.js","sourceRoot":"","sources":["../src/TextInput.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,KAAK,EAA4C,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAmC7B,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,EAAE,EACF,IAAI,EACJ,KAAK,EACL,UAAU,EACV,MAAM,EACN,MAAM,EACN,SAAS,EACT,GAAG,IAAI,EACQ;IACf,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,EAAE,IAAI,WAAW,CAAC;IAClC,MAAM,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC;IACjC,MAAM,OAAO,GAAG,GAAG,OAAO,QAAQ,CAAC;IAEnC,iFAAiF;IACjF,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;IAE1G,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,oBAAoB,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,MAAM,KAAK,GAAG,CACZ,gBACE,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC,sBACrD,WAAW,kBAEf,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,KAClC,IAAI,GACR,CACH,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,aACrE,gBAAO,SAAS,EAAC,kBAAkB,EAAC,OAAO,EAAE,OAAO,YACjD,KAAK,GACA,EACP,IAAI,IAAI,CACP,eAAM,SAAS,EAAC,iBAAiB,EAAC,EAAE,EAAE,MAAM,YACzC,IAAI,GACA,CACR,EACA,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,CAClB,gBAAM,SAAS,EAAE,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,aAC9C,MAAM,IAAI,eAAM,SAAS,EAAC,wBAAwB,YAAE,MAAM,GAAQ,EAClE,KAAK,EACL,MAAM,IAAI,eAAM,SAAS,EAAC,wBAAwB,YAAE,MAAM,GAAQ,IAC9D,CACR,CAAC,CAAC,CAAC,CACF,KAAK,CACN,EACA,KAAK,IAAI,CACR,gBAAM,SAAS,EAAC,kBAAkB,EAAC,EAAE,EAAE,OAAO,aAC5C,cAAK,SAAS,EAAC,uBAAuB,EAAC,OAAO,EAAC,WAAW,iBAAa,MAAM,EAAC,IAAI,EAAC,cAAc,YAC/F,eAAM,CAAC,EAAC,oEAAoE,GAAG,GAC3E,EACL,KAAK,IACD,CACR,IACG,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type ColorMode, type ThemeState } from "./themeCore.js";
|
|
3
|
+
export { applyTheme, themeInitScript } from "./themeCore.js";
|
|
4
|
+
export type { ColorMode, Language, Calendar, Density, ThemeState } from "./themeCore.js";
|
|
5
|
+
/**
|
|
6
|
+
* The theme provider — the single place where rendering context is set (§10.2, normative).
|
|
7
|
+
*
|
|
8
|
+
* It controls display mode, language, calendar, and density, applies them as root attributes that
|
|
9
|
+
* @govnepal/tokens keys off, and persists the user's choices. Exactly one provider is expected at
|
|
10
|
+
* the application root; a nested provider may override the DISPLAY MODE for a subtree (a mode
|
|
11
|
+
* preview) but nothing else — language never changes mid-page except through a visible switcher.
|
|
12
|
+
*/
|
|
13
|
+
export interface ThemeContextValue extends ThemeState {
|
|
14
|
+
setColorMode: (mode: ColorMode | undefined) => void;
|
|
15
|
+
setLargeText: (on: boolean) => void;
|
|
16
|
+
setReducedMotion: (on: boolean) => void;
|
|
17
|
+
setLanguage: (language: ThemeState["language"]) => void;
|
|
18
|
+
setCalendar: (calendar: ThemeState["calendar"]) => void;
|
|
19
|
+
/** The active mode after OS fallback is resolved — for a UI that needs the current state. */
|
|
20
|
+
resolvedColorMode: ColorMode;
|
|
21
|
+
}
|
|
22
|
+
export interface ThemeProviderProps extends Partial<ThemeState> {
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
/**
|
|
25
|
+
* A nested provider overrides only the display mode for its subtree (§10.2 — a mode preview).
|
|
26
|
+
* It renders a wrapper element carrying the mode attributes and does not touch <html>, storage,
|
|
27
|
+
* language, or the OS listeners.
|
|
28
|
+
*/
|
|
29
|
+
nested?: boolean;
|
|
30
|
+
/** Persist device-side changes. A signed-in app sets this false and persists to the account. */
|
|
31
|
+
persist?: boolean;
|
|
32
|
+
/** Called on any change, so a signed-in app can write the choice to the user's account. */
|
|
33
|
+
onChange?: (state: ThemeState) => void;
|
|
34
|
+
}
|
|
35
|
+
export declare function ThemeProvider({ children, nested, persist, onChange, ...overrides }: ThemeProviderProps): ReactNode;
|
|
36
|
+
export declare function useTheme(): ThemeContextValue;
|
|
37
|
+
//# sourceMappingURL=ThemeProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../src/ThemeProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7D,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEzF;;;;;;;GAOG;AAEH,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,CAAC;IACpD,YAAY,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,gBAAgB,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,WAAW,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACxD,WAAW,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACxD,6FAA6F;IAC7F,iBAAiB,EAAE,SAAS,CAAC;CAC9B;AAID,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CAAC,UAAU,CAAC;IAC7D,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gGAAgG;IAChG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACxC;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAc,EACd,OAAc,EACd,QAAQ,EACR,GAAG,SAAS,EACb,EAAE,kBAAkB,GAAG,SAAS,CAkFhC;AAED,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
4
|
+
import { applyTheme, loadPersistedTheme, THEME_DEFAULTS, THEME_STORAGE_KEY, } from "./themeCore.js";
|
|
5
|
+
// Server-safe utilities and types live in themeCore; re-export them so consumers have one import.
|
|
6
|
+
export { applyTheme, themeInitScript } from "./themeCore.js";
|
|
7
|
+
const ThemeContext = createContext(null);
|
|
8
|
+
export function ThemeProvider({ children, nested = false, persist = true, onChange, ...overrides }) {
|
|
9
|
+
const [state, setState] = useState(() => ({
|
|
10
|
+
...THEME_DEFAULTS,
|
|
11
|
+
...(nested ? {} : loadPersistedTheme()),
|
|
12
|
+
...overrides,
|
|
13
|
+
}));
|
|
14
|
+
const nestedRef = useRef(null);
|
|
15
|
+
// An override prop that CHANGES after mount wins — this is what makes a nested mode-preview panel
|
|
16
|
+
// reactive: change its `colorMode` prop and the subtree updates. A prop that stays constant does
|
|
17
|
+
// not clobber a user's own switcher choice, because the effect fires only on a real value change.
|
|
18
|
+
const overridesKey = JSON.stringify(overrides);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
const next = JSON.parse(overridesKey);
|
|
21
|
+
if (Object.keys(next).length > 0)
|
|
22
|
+
setState((prev) => ({ ...prev, ...next }));
|
|
23
|
+
}, [overridesKey]);
|
|
24
|
+
// Apply to <html> for the root provider, or to the wrapper div for a nested one.
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (nested) {
|
|
27
|
+
if (nestedRef.current)
|
|
28
|
+
applyTheme(nestedRef.current, state);
|
|
29
|
+
}
|
|
30
|
+
else if (typeof document !== "undefined") {
|
|
31
|
+
applyTheme(document.documentElement, state);
|
|
32
|
+
}
|
|
33
|
+
}, [nested, state]);
|
|
34
|
+
// Persist and notify on change (root provider only — a nested preview is ephemeral).
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (nested)
|
|
37
|
+
return;
|
|
38
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
39
|
+
try {
|
|
40
|
+
localStorage.setItem(THEME_STORAGE_KEY, JSON.stringify(state));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// A private-mode browser can refuse storage; the choice still holds for the session.
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
onChange?.(state);
|
|
47
|
+
}, [nested, persist, onChange, state]);
|
|
48
|
+
// Track the OS color preference so `resolvedColorMode` is accurate while colorMode is undefined.
|
|
49
|
+
const [osMode, setOsMode] = useState("light");
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (typeof matchMedia === "undefined")
|
|
52
|
+
return;
|
|
53
|
+
const dark = matchMedia("(prefers-color-scheme: dark)");
|
|
54
|
+
const contrast = matchMedia("(prefers-contrast: more)");
|
|
55
|
+
const resolve = () => setOsMode(contrast.matches ? "high-contrast" : dark.matches ? "dark" : "light");
|
|
56
|
+
resolve();
|
|
57
|
+
dark.addEventListener("change", resolve);
|
|
58
|
+
contrast.addEventListener("change", resolve);
|
|
59
|
+
return () => {
|
|
60
|
+
dark.removeEventListener("change", resolve);
|
|
61
|
+
contrast.removeEventListener("change", resolve);
|
|
62
|
+
};
|
|
63
|
+
}, []);
|
|
64
|
+
const update = useCallback((partial) => {
|
|
65
|
+
setState((prev) => ({ ...prev, ...partial }));
|
|
66
|
+
}, []);
|
|
67
|
+
const value = useMemo(() => ({
|
|
68
|
+
...state,
|
|
69
|
+
resolvedColorMode: state.colorMode ?? osMode,
|
|
70
|
+
setColorMode: (colorMode) => update({ colorMode }),
|
|
71
|
+
setLargeText: (largeText) => update({ largeText }),
|
|
72
|
+
setReducedMotion: (reducedMotion) => update({ reducedMotion }),
|
|
73
|
+
setLanguage: (language) => update({ language }),
|
|
74
|
+
setCalendar: (calendar) => update({ calendar }),
|
|
75
|
+
}), [state, osMode, update]);
|
|
76
|
+
if (nested) {
|
|
77
|
+
return (_jsx(ThemeContext.Provider, { value: value, children: _jsx("div", { ref: nestedRef, children: children }) }));
|
|
78
|
+
}
|
|
79
|
+
return _jsx(ThemeContext.Provider, { value: value, children: children });
|
|
80
|
+
}
|
|
81
|
+
export function useTheme() {
|
|
82
|
+
const value = useContext(ThemeContext);
|
|
83
|
+
if (!value) {
|
|
84
|
+
throw new Error("useTheme must be used within a <ThemeProvider>. It is the app's single root provider (§10.2).");
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=ThemeProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeProvider.js","sourceRoot":"","sources":["../src/ThemeProvider.tsx"],"names":[],"mappings":"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"}
|
package/dist/cx.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Join class names, dropping falsy ones. No dependency needed for something this small. */
|
|
2
|
+
export declare function cx(...parts: Array<string | false | null | undefined>): string;
|
|
3
|
+
/** The spacing steps that exist as tokens (space.* in the guidelines). Used to type `gap`. */
|
|
4
|
+
export type SpaceStep = 1 | 2 | 3 | 4 | 6 | 8;
|
|
5
|
+
//# sourceMappingURL=cx.d.ts.map
|
package/dist/cx.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cx.d.ts","sourceRoot":"","sources":["../src/cx.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,wBAAgB,EAAE,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAE7E;AAED,8FAA8F;AAC9F,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC"}
|
package/dist/cx.js
ADDED
package/dist/cx.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cx.js","sourceRoot":"","sources":["../src/cx.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,MAAM,UAAU,EAAE,CAAC,GAAG,KAA+C;IACnE,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type StatusId = "draft" | "submitted" | "under-review" | "correction-required" | "approved" | "rejected" | "printed" | "delivered";
|
|
2
|
+
export type BadgeVariant = "neutral" | "info" | "success" | "warning" | "error";
|
|
3
|
+
export interface StatusEntry {
|
|
4
|
+
label: string;
|
|
5
|
+
label_ne: string;
|
|
6
|
+
badge: BadgeVariant;
|
|
7
|
+
/** correction-required is the one status that must sit beside an action link (§7.3.2). */
|
|
8
|
+
requiresAction: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const STATUS_TAXONOMY: Record<StatusId, StatusEntry>;
|
|
11
|
+
//# sourceMappingURL=statusTaxonomy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusTaxonomy.d.ts","sourceRoot":"","sources":["../../src/generated/statusTaxonomy.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,qBAAqB,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,CAAC;AAC1I,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,0FAA0F;IAC1F,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,CASzD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// GENERATED from design-guidelines 0.2.0-dev (7af0babf) — do not edit.
|
|
2
|
+
// Source: data/status-taxonomy.yaml (§7.3.2). Regenerate with build/generate.mjs.
|
|
3
|
+
export const STATUS_TAXONOMY = {
|
|
4
|
+
"draft": { label: "Draft", label_ne: "मस्यौदा", badge: "neutral", requiresAction: false },
|
|
5
|
+
"submitted": { label: "Submitted", label_ne: "पेश गरिएको", badge: "info", requiresAction: false },
|
|
6
|
+
"under-review": { label: "Under review", label_ne: "समीक्षा हुँदै", badge: "info", requiresAction: false },
|
|
7
|
+
"correction-required": { label: "Correction required", label_ne: "सुधार आवश्यक", badge: "warning", requiresAction: true },
|
|
8
|
+
"approved": { label: "Approved", label_ne: "स्वीकृत", badge: "success", requiresAction: false },
|
|
9
|
+
"rejected": { label: "Rejected", label_ne: "अस्वीकृत", badge: "error", requiresAction: false },
|
|
10
|
+
"printed": { label: "Printed", label_ne: "छापिएको", badge: "neutral", requiresAction: false },
|
|
11
|
+
"delivered": { label: "Delivered", label_ne: "वितरण गरिएको", badge: "success", requiresAction: false },
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=statusTaxonomy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusTaxonomy.js","sourceRoot":"","sources":["../../src/generated/statusTaxonomy.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,kFAAkF;AAalF,MAAM,CAAC,MAAM,eAAe,GAAkC;IAC5D,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE;IACzF,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE;IACjG,cAAc,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE;IAC1G,qBAAqB,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE;IACzH,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE;IAC/F,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE;IAC9F,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE;IAC7F,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE;CACvG,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @govnepal/ui — the Civic Calm React behavior layer.
|
|
3
|
+
*
|
|
4
|
+
* These components add ARIA, keyboard handling, and focus management on top of @govnepal/css.
|
|
5
|
+
* They contain no styling of their own: every visual decision lives in the stylesheet, so a
|
|
6
|
+
* consumer must load @govnepal/css and @govnepal/tokens alongside this package. The split is
|
|
7
|
+
* deliberate — a future Vue or Web Component port re-implements behavior only, never design.
|
|
8
|
+
*/
|
|
9
|
+
export { applyTheme, themeInitScript } from "./themeCore.js";
|
|
10
|
+
export type { ColorMode, Language, Calendar, Density, ThemeState } from "./themeCore.js";
|
|
11
|
+
export { ThemeProvider, useTheme } from "./ThemeProvider.js";
|
|
12
|
+
export type { ThemeContextValue, ThemeProviderProps } from "./ThemeProvider.js";
|
|
13
|
+
export { Container, Stack, PageSection } from "./layout.js";
|
|
14
|
+
export { Button } from "./Button.js";
|
|
15
|
+
export { Link } from "./Link.js";
|
|
16
|
+
export { TextInput } from "./TextInput.js";
|
|
17
|
+
export { ErrorSummary, type FieldError } from "./ErrorSummary.js";
|
|
18
|
+
export { Alert } from "./Alert.js";
|
|
19
|
+
export { Badge } from "./Badge.js";
|
|
20
|
+
export { Header } from "./Header.js";
|
|
21
|
+
export { STATUS_TAXONOMY, type StatusId, type StatusEntry, type BadgeVariant } from "./generated/statusTaxonomy.js";
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7D,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEhF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,+BAA+B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @govnepal/ui — the Civic Calm React behavior layer.
|
|
3
|
+
*
|
|
4
|
+
* These components add ARIA, keyboard handling, and focus management on top of @govnepal/css.
|
|
5
|
+
* They contain no styling of their own: every visual decision lives in the stylesheet, so a
|
|
6
|
+
* consumer must load @govnepal/css and @govnepal/tokens alongside this package. The split is
|
|
7
|
+
* deliberate — a future Vue or Web Component port re-implements behavior only, never design.
|
|
8
|
+
*/
|
|
9
|
+
// Server-safe theme utilities come straight from themeCore (no "use client"), so a React Server
|
|
10
|
+
// Component — e.g. a Next.js root layout — can inline themeInitScript in <head> without importing
|
|
11
|
+
// the client-only provider. The provider and hook come from ThemeProvider ("use client").
|
|
12
|
+
export { applyTheme, themeInitScript } from "./themeCore.js";
|
|
13
|
+
export { ThemeProvider, useTheme } from "./ThemeProvider.js";
|
|
14
|
+
export { Container, Stack, PageSection } from "./layout.js";
|
|
15
|
+
export { Button } from "./Button.js";
|
|
16
|
+
export { Link } from "./Link.js";
|
|
17
|
+
export { TextInput } from "./TextInput.js";
|
|
18
|
+
export { ErrorSummary } from "./ErrorSummary.js";
|
|
19
|
+
export { Alert } from "./Alert.js";
|
|
20
|
+
export { Badge } from "./Badge.js";
|
|
21
|
+
export { Header } from "./Header.js";
|
|
22
|
+
export { STATUS_TAXONOMY } from "./generated/statusTaxonomy.js";
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gGAAgG;AAChG,kGAAkG;AAClG,0FAA0F;AAC1F,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,eAAe,EAAsD,MAAM,+BAA+B,CAAC"}
|
package/dist/layout.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ElementType, HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import { type SpaceStep } from "./cx.js";
|
|
3
|
+
/**
|
|
4
|
+
* The layout primitives (components/container.md, stack.md, page-section.md) — "the grid made
|
|
5
|
+
* installable", the only sanctioned way to set page width, vertical rhythm, and page bands, so
|
|
6
|
+
* spacing never appears hardcoded in product code. They add behavior only in one respect: the
|
|
7
|
+
* `as` prop, so a stack of form fields can be a <fieldset> and a page section can be a <section>
|
|
8
|
+
* with a heading — the semantics the spec requires, which pure CSS classes cannot supply.
|
|
9
|
+
*/
|
|
10
|
+
interface ContainerProps extends HTMLAttributes<HTMLElement> {
|
|
11
|
+
variant?: "default" | "narrow" | "full-bleed";
|
|
12
|
+
as?: ElementType;
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export declare function Container({ variant, as: As, className, children, ...rest }: ContainerProps): import("react").JSX.Element;
|
|
16
|
+
interface StackProps extends HTMLAttributes<HTMLElement> {
|
|
17
|
+
/** Spacing token step only — an arbitrary pixel gap is a checker violation (components/stack.md). */
|
|
18
|
+
gap?: SpaceStep;
|
|
19
|
+
as?: ElementType;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
}
|
|
22
|
+
export declare function Stack({ gap, as: As, className, children, ...rest }: StackProps): import("react").JSX.Element;
|
|
23
|
+
interface PageSectionProps extends HTMLAttributes<HTMLElement> {
|
|
24
|
+
variant?: "default" | "secondary-background" | "inverse";
|
|
25
|
+
/**
|
|
26
|
+
* A page section becomes a labelled landmark region only when it has an accessible name;
|
|
27
|
+
* otherwise it is presentation-only (components/page-section.md). Passing `aria-label` (or a
|
|
28
|
+
* heading via `labelledBy`) is what upgrades it to <section role="region">.
|
|
29
|
+
*/
|
|
30
|
+
labelledBy?: string;
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
}
|
|
33
|
+
export declare function PageSection({ variant, labelledBy, className, children, "aria-label": ariaLabel, ...rest }: PageSectionProps): import("react").JSX.Element;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,EAAM,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;;GAMG;AAEH,UAAU,cAAe,SAAQ,cAAc,CAAC,WAAW,CAAC;IAC1D,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC9C,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,SAAS,CAAC,EAAE,OAAmB,EAAE,EAAE,EAAE,EAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,cAAc,+BAS9G;AAED,UAAU,UAAW,SAAQ,cAAc,CAAC,WAAW,CAAC;IACtD,qGAAqG;IACrG,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,KAAK,CAAC,EAAE,GAAO,EAAE,EAAE,EAAE,EAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,UAAU,+BAM1F;AAED,UAAU,gBAAiB,SAAQ,cAAc,CAAC,WAAW,CAAC;IAC5D,OAAO,CAAC,EAAE,SAAS,GAAG,sBAAsB,GAAG,SAAS,CAAC;IACzD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAC1B,OAAmB,EACnB,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,EAAE,SAAS,EACvB,GAAG,IAAI,EACR,EAAE,gBAAgB,+BAsBlB"}
|
package/dist/layout.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cx } from "./cx.js";
|
|
3
|
+
export function Container({ variant = "default", as: As = "div", className, children, ...rest }) {
|
|
4
|
+
return (_jsx(As, { className: cx("gov-container", variant !== "default" && `gov-container--${variant}`, className), ...rest, children: children }));
|
|
5
|
+
}
|
|
6
|
+
export function Stack({ gap = 4, as: As = "div", className, children, ...rest }) {
|
|
7
|
+
return (_jsx(As, { className: cx("gov-stack", `gov-stack--${gap}`, className), ...rest, children: children }));
|
|
8
|
+
}
|
|
9
|
+
export function PageSection({ variant = "default", labelledBy, className, children, "aria-label": ariaLabel, ...rest }) {
|
|
10
|
+
const className_ = cx("gov-page-section", variant !== "default" && `gov-page-section--${variant}`, className);
|
|
11
|
+
// A named band is a landmark region; an unnamed one is a plain div. A <section> with no
|
|
12
|
+
// accessible name is not exposed as a landmark anyway, so rendering a div when unnamed is
|
|
13
|
+
// both honest and avoids a meaningless generic region in the accessibility tree.
|
|
14
|
+
if (labelledBy || ariaLabel) {
|
|
15
|
+
return (_jsx("section", { className: className_, "aria-labelledby": labelledBy, "aria-label": ariaLabel, ...rest, children: children }));
|
|
16
|
+
}
|
|
17
|
+
return (_jsx("div", { className: className_, ...rest, children: children }));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAkB,MAAM,SAAS,CAAC;AAgB7C,MAAM,UAAU,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAkB;IAC7G,OAAO,CACL,KAAC,EAAE,IACD,SAAS,EAAE,EAAE,CAAC,eAAe,EAAE,OAAO,KAAK,SAAS,IAAI,kBAAkB,OAAO,EAAE,EAAE,SAAS,CAAC,KAC3F,IAAI,YAEP,QAAQ,GACN,CACN,CAAC;AACJ,CAAC;AASD,MAAM,UAAU,KAAK,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAc;IACzF,OAAO,CACL,KAAC,EAAE,IAAC,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,cAAc,GAAG,EAAE,EAAE,SAAS,CAAC,KAAM,IAAI,YACrE,QAAQ,GACN,CACN,CAAC;AACJ,CAAC;AAaD,MAAM,UAAU,WAAW,CAAC,EAC1B,OAAO,GAAG,SAAS,EACnB,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,EAAE,SAAS,EACvB,GAAG,IAAI,EACU;IACjB,MAAM,UAAU,GAAG,EAAE,CACnB,kBAAkB,EAClB,OAAO,KAAK,SAAS,IAAI,qBAAqB,OAAO,EAAE,EACvD,SAAS,CACV,CAAC;IAEF,wFAAwF;IACxF,0FAA0F;IAC1F,iFAAiF;IACjF,IAAI,UAAU,IAAI,SAAS,EAAE,CAAC;QAC5B,OAAO,CACL,kBAAS,SAAS,EAAE,UAAU,qBAAmB,UAAU,gBAAc,SAAS,KAAM,IAAI,YACzF,QAAQ,GACD,CACX,CAAC;IACJ,CAAC;IACD,OAAO,CACL,cAAK,SAAS,EAAE,UAAU,KAAM,IAAI,YACjC,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-safe theme utilities — no React, no hooks, no "use client".
|
|
3
|
+
*
|
|
4
|
+
* Split out from ThemeProvider so a React Server Component (e.g. a Next.js root layout) can import
|
|
5
|
+
* `themeInitScript` to inline in <head>, and `applyTheme` if it needs it, without pulling the
|
|
6
|
+
* client-only provider across the server/client boundary. The provider itself lives in
|
|
7
|
+
* ThemeProvider.tsx and re-exports these.
|
|
8
|
+
*/
|
|
9
|
+
/** The four color modes (§5.2). large-text and reduced-motion are separate, composable flags. */
|
|
10
|
+
export type ColorMode = "light" | "dark" | "high-contrast" | "color-blind-safe";
|
|
11
|
+
export type Language = "ne" | "en";
|
|
12
|
+
export type Calendar = "BS" | "AD";
|
|
13
|
+
/** Matches data/density-rules.yaml ids. */
|
|
14
|
+
export type Density = "citizen-website" | "citizen-mobile-app" | "officer-desktop-app" | "kiosk-counter";
|
|
15
|
+
export interface ThemeState {
|
|
16
|
+
/** Undefined means "follow the OS" — the default until the user chooses explicitly (§10.2). */
|
|
17
|
+
colorMode: ColorMode | undefined;
|
|
18
|
+
largeText: boolean;
|
|
19
|
+
reducedMotion: boolean;
|
|
20
|
+
language: Language;
|
|
21
|
+
calendar: Calendar;
|
|
22
|
+
density: Density;
|
|
23
|
+
}
|
|
24
|
+
export declare const THEME_STORAGE_KEY = "gov-theme";
|
|
25
|
+
export declare const THEME_DEFAULTS: ThemeState;
|
|
26
|
+
/** Read persisted choices. Device storage is the fallback; a signed-in app passes them via props. */
|
|
27
|
+
export declare function loadPersistedTheme(): Partial<ThemeState>;
|
|
28
|
+
/**
|
|
29
|
+
* Apply the theme to a root element as data-attributes. This is the entire coupling between state
|
|
30
|
+
* and the token layer: @govnepal/tokens' CSS selectors ([data-mode], [data-large-text], …) do the
|
|
31
|
+
* rest. Attributes are removed rather than set to a falsy value so the OS-default selectors
|
|
32
|
+
* (:root:not([data-mode])) engage when the user has made no explicit choice.
|
|
33
|
+
*/
|
|
34
|
+
export declare function applyTheme(root: HTMLElement, state: ThemeState): void;
|
|
35
|
+
/**
|
|
36
|
+
* The <script> to inline in <head> BEFORE first paint, so the persisted mode is on <html> before
|
|
37
|
+
* any content renders — no flash of the wrong theme. A server layout renders this as a raw string;
|
|
38
|
+
* it deliberately duplicates a little of applyTheme() because it must run without React.
|
|
39
|
+
*/
|
|
40
|
+
export declare const themeInitScript: string;
|
|
41
|
+
//# sourceMappingURL=themeCore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themeCore.d.ts","sourceRoot":"","sources":["../src/themeCore.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,iGAAiG;AACjG,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAChF,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;AACnC,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;AACnC,2CAA2C;AAC3C,MAAM,MAAM,OAAO,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,qBAAqB,GAAG,eAAe,CAAC;AAEzG,MAAM,WAAW,UAAU;IACzB,+FAA+F;IAC/F,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C,eAAO,MAAM,cAAc,EAAE,UAO5B,CAAC;AAEF,qGAAqG;AACrG,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,UAAU,CAAC,CAQxD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAUrE;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAE8S,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-safe theme utilities — no React, no hooks, no "use client".
|
|
3
|
+
*
|
|
4
|
+
* Split out from ThemeProvider so a React Server Component (e.g. a Next.js root layout) can import
|
|
5
|
+
* `themeInitScript` to inline in <head>, and `applyTheme` if it needs it, without pulling the
|
|
6
|
+
* client-only provider across the server/client boundary. The provider itself lives in
|
|
7
|
+
* ThemeProvider.tsx and re-exports these.
|
|
8
|
+
*/
|
|
9
|
+
export const THEME_STORAGE_KEY = "gov-theme";
|
|
10
|
+
export const THEME_DEFAULTS = {
|
|
11
|
+
colorMode: undefined,
|
|
12
|
+
largeText: false,
|
|
13
|
+
reducedMotion: false,
|
|
14
|
+
language: "ne", // Nepali-first (Article 7) — the default language of official business.
|
|
15
|
+
calendar: "BS", // Bikram Sambat is the administrative calendar of record (§3.1).
|
|
16
|
+
density: "citizen-website",
|
|
17
|
+
};
|
|
18
|
+
/** Read persisted choices. Device storage is the fallback; a signed-in app passes them via props. */
|
|
19
|
+
export function loadPersistedTheme() {
|
|
20
|
+
if (typeof localStorage === "undefined")
|
|
21
|
+
return {};
|
|
22
|
+
try {
|
|
23
|
+
const raw = localStorage.getItem(THEME_STORAGE_KEY);
|
|
24
|
+
return raw ? JSON.parse(raw) : {};
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Apply the theme to a root element as data-attributes. This is the entire coupling between state
|
|
32
|
+
* and the token layer: @govnepal/tokens' CSS selectors ([data-mode], [data-large-text], …) do the
|
|
33
|
+
* rest. Attributes are removed rather than set to a falsy value so the OS-default selectors
|
|
34
|
+
* (:root:not([data-mode])) engage when the user has made no explicit choice.
|
|
35
|
+
*/
|
|
36
|
+
export function applyTheme(root, state) {
|
|
37
|
+
if (state.colorMode)
|
|
38
|
+
root.setAttribute("data-mode", state.colorMode);
|
|
39
|
+
else
|
|
40
|
+
root.removeAttribute("data-mode");
|
|
41
|
+
root.toggleAttribute("data-large-text", state.largeText);
|
|
42
|
+
if (state.reducedMotion)
|
|
43
|
+
root.setAttribute("data-reduced-motion", "true");
|
|
44
|
+
else
|
|
45
|
+
root.removeAttribute("data-reduced-motion");
|
|
46
|
+
root.setAttribute("data-density", state.density);
|
|
47
|
+
root.setAttribute("lang", state.language);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The <script> to inline in <head> BEFORE first paint, so the persisted mode is on <html> before
|
|
51
|
+
* any content renders — no flash of the wrong theme. A server layout renders this as a raw string;
|
|
52
|
+
* it deliberately duplicates a little of applyTheme() because it must run without React.
|
|
53
|
+
*/
|
|
54
|
+
export const themeInitScript = `(function(){try{var s=JSON.parse(localStorage.getItem(${JSON.stringify(THEME_STORAGE_KEY)})||"{}");var r=document.documentElement;if(s.colorMode)r.setAttribute("data-mode",s.colorMode);if(s.largeText)r.setAttribute("data-large-text","");if(s.reducedMotion)r.setAttribute("data-reduced-motion","true");r.setAttribute("data-density",s.density||"citizen-website");r.setAttribute("lang",s.language||"ne");}catch(e){}})();`;
|
|
55
|
+
//# sourceMappingURL=themeCore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themeCore.js","sourceRoot":"","sources":["../src/themeCore.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAmBH,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE7C,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,SAAS,EAAE,SAAS;IACpB,SAAS,EAAE,KAAK;IAChB,aAAa,EAAE,KAAK;IACpB,QAAQ,EAAE,IAAI,EAAE,wEAAwE;IACxF,QAAQ,EAAE,IAAI,EAAE,iEAAiE;IACjF,OAAO,EAAE,iBAAiB;CAC3B,CAAC;AAEF,qGAAqG;AACrG,MAAM,UAAU,kBAAkB;IAChC,IAAI,OAAO,YAAY,KAAK,WAAW;QAAE,OAAO,EAAE,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACpD,OAAO,GAAG,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAiB,EAAE,KAAiB;IAC7D,IAAI,KAAK,CAAC,SAAS;QAAE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;;QAChE,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IAEvC,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACzD,IAAI,KAAK,CAAC,aAAa;QAAE,IAAI,CAAC,YAAY,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;;QACrE,IAAI,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC;IAEjD,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,yDAAyD,IAAI,CAAC,SAAS,CACpG,iBAAiB,CAClB,yUAAyU,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@govnepal/ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Civic Calm React components — the behavior layer (ARIA, keyboard, focus) over @govnepal/css.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"nepal",
|
|
9
|
+
"government",
|
|
10
|
+
"design-system",
|
|
11
|
+
"civic-calm",
|
|
12
|
+
"react",
|
|
13
|
+
"components",
|
|
14
|
+
"a11y"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://github.com/govnepal/design-web/tree/main/packages/ui#readme",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/govnepal/design-web.git",
|
|
20
|
+
"directory": "packages/ui"
|
|
21
|
+
},
|
|
22
|
+
"bugs": "https://github.com/govnepal/design-web/issues",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"react": ">=18",
|
|
37
|
+
"react-dom": ">=18"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@govnepal/css": "^0.1.0",
|
|
41
|
+
"@govnepal/tokens": "^0.1.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@testing-library/dom": "^10.4.1",
|
|
45
|
+
"@testing-library/react": "^16.3.2",
|
|
46
|
+
"@types/react": "^19.0.0",
|
|
47
|
+
"global-jsdom": "^29.0.0",
|
|
48
|
+
"jsdom": "^29.1.1",
|
|
49
|
+
"react": "^19.2.0",
|
|
50
|
+
"react-dom": "^19.2.0",
|
|
51
|
+
"yaml": "^2.9.0"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"generate": "node build/generate.mjs",
|
|
55
|
+
"build": "node build/generate.mjs && tsc -p tsconfig.build.json",
|
|
56
|
+
"typecheck": "node build/generate.mjs && tsc -p tsconfig.build.json --noEmit",
|
|
57
|
+
"test": "node --import ./test/setup.mjs --test"
|
|
58
|
+
}
|
|
59
|
+
}
|