@northstar-js/react 0.0.0-stage → 0.2.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 (182) hide show
  1. package/LICENSE +21 -0
  2. package/dist/actions.d.ts +99 -0
  3. package/dist/actions.d.ts.map +1 -0
  4. package/dist/actions.js +61 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/backdrops/StarBackdrop.d.ts +31 -0
  7. package/dist/backdrops/StarBackdrop.d.ts.map +1 -0
  8. package/dist/backdrops/StarBackdrop.js +84 -0
  9. package/dist/backdrops/StarBackdrop.js.map +1 -0
  10. package/dist/backdrops/index.d.ts +7 -0
  11. package/dist/backdrops/index.d.ts.map +1 -0
  12. package/dist/backdrops/index.js +8 -0
  13. package/dist/backdrops/index.js.map +1 -0
  14. package/dist/backdrops/math.d.ts +39 -0
  15. package/dist/backdrops/math.d.ts.map +1 -0
  16. package/dist/backdrops/math.js +44 -0
  17. package/dist/backdrops/math.js.map +1 -0
  18. package/dist/backdrops/scenes.d.ts +20 -0
  19. package/dist/backdrops/scenes.d.ts.map +1 -0
  20. package/dist/backdrops/scenes.js +417 -0
  21. package/dist/backdrops/scenes.js.map +1 -0
  22. package/dist/backdrops.css +141 -0
  23. package/dist/data.d.ts +91 -0
  24. package/dist/data.d.ts.map +1 -0
  25. package/dist/data.js +69 -0
  26. package/dist/data.js.map +1 -0
  27. package/dist/effects/actions.d.ts +48 -0
  28. package/dist/effects/actions.d.ts.map +1 -0
  29. package/dist/effects/actions.js +80 -0
  30. package/dist/effects/actions.js.map +1 -0
  31. package/dist/effects/controls.d.ts +84 -0
  32. package/dist/effects/controls.d.ts.map +1 -0
  33. package/dist/effects/controls.js +121 -0
  34. package/dist/effects/controls.js.map +1 -0
  35. package/dist/effects/display.d.ts +92 -0
  36. package/dist/effects/display.d.ts.map +1 -0
  37. package/dist/effects/display.js +138 -0
  38. package/dist/effects/display.js.map +1 -0
  39. package/dist/effects/hooks.d.ts +13 -0
  40. package/dist/effects/hooks.d.ts.map +1 -0
  41. package/dist/effects/hooks.js +68 -0
  42. package/dist/effects/hooks.js.map +1 -0
  43. package/dist/effects/index.d.ts +14 -0
  44. package/dist/effects/index.d.ts.map +1 -0
  45. package/dist/effects/index.js +12 -0
  46. package/dist/effects/index.js.map +1 -0
  47. package/dist/effects/loaders.d.ts +67 -0
  48. package/dist/effects/loaders.d.ts.map +1 -0
  49. package/dist/effects/loaders.js +73 -0
  50. package/dist/effects/loaders.js.map +1 -0
  51. package/dist/effects/math.d.ts +23 -0
  52. package/dist/effects/math.d.ts.map +1 -0
  53. package/dist/effects/math.js +56 -0
  54. package/dist/effects/math.js.map +1 -0
  55. package/dist/effects/navigation.d.ts +55 -0
  56. package/dist/effects/navigation.d.ts.map +1 -0
  57. package/dist/effects/navigation.js +103 -0
  58. package/dist/effects/navigation.js.map +1 -0
  59. package/dist/effects/overlays.d.ts +34 -0
  60. package/dist/effects/overlays.d.ts.map +1 -0
  61. package/dist/effects/overlays.js +56 -0
  62. package/dist/effects/overlays.js.map +1 -0
  63. package/dist/effects.css +1659 -0
  64. package/dist/feedback.d.ts +55 -0
  65. package/dist/feedback.d.ts.map +1 -0
  66. package/dist/feedback.js +60 -0
  67. package/dist/feedback.js.map +1 -0
  68. package/dist/flow.d.ts +70 -0
  69. package/dist/flow.d.ts.map +1 -0
  70. package/dist/flow.js +118 -0
  71. package/dist/flow.js.map +1 -0
  72. package/dist/forms.d.ts +130 -0
  73. package/dist/forms.d.ts.map +1 -0
  74. package/dist/forms.js +241 -0
  75. package/dist/forms.js.map +1 -0
  76. package/dist/glass.d.ts +74 -0
  77. package/dist/glass.d.ts.map +1 -0
  78. package/dist/glass.js +139 -0
  79. package/dist/glass.js.map +1 -0
  80. package/dist/illustrations/data.d.ts +103 -0
  81. package/dist/illustrations/data.d.ts.map +1 -0
  82. package/dist/illustrations/data.js +3 -0
  83. package/dist/illustrations/data.js.map +1 -0
  84. package/dist/illustrations/index.d.ts +110 -0
  85. package/dist/illustrations/index.d.ts.map +1 -0
  86. package/dist/illustrations/index.js +54 -0
  87. package/dist/illustrations/index.js.map +1 -0
  88. package/dist/illustrations/types.d.ts +30 -0
  89. package/dist/illustrations/types.d.ts.map +1 -0
  90. package/dist/illustrations/types.js +2 -0
  91. package/dist/illustrations/types.js.map +1 -0
  92. package/dist/index.d.ts +27 -0
  93. package/dist/index.d.ts.map +1 -0
  94. package/dist/index.js +13 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/internal/expand.d.ts +17 -0
  97. package/dist/internal/expand.d.ts.map +1 -0
  98. package/dist/internal/expand.js +23 -0
  99. package/dist/internal/expand.js.map +1 -0
  100. package/dist/internal/icons.d.ts +9 -0
  101. package/dist/internal/icons.d.ts.map +1 -0
  102. package/dist/internal/icons.js +12 -0
  103. package/dist/internal/icons.js.map +1 -0
  104. package/dist/internal/interaction.d.ts +21 -0
  105. package/dist/internal/interaction.d.ts.map +1 -0
  106. package/dist/internal/interaction.js +129 -0
  107. package/dist/internal/interaction.js.map +1 -0
  108. package/dist/internal/layers.d.ts +12 -0
  109. package/dist/internal/layers.d.ts.map +1 -0
  110. package/dist/internal/layers.js +108 -0
  111. package/dist/internal/layers.js.map +1 -0
  112. package/dist/internal/util.d.ts +9 -0
  113. package/dist/internal/util.d.ts.map +1 -0
  114. package/dist/internal/util.js +33 -0
  115. package/dist/internal/util.js.map +1 -0
  116. package/dist/layout.d.ts +34 -0
  117. package/dist/layout.d.ts.map +1 -0
  118. package/dist/layout.js +27 -0
  119. package/dist/layout.js.map +1 -0
  120. package/dist/motion.d.ts +36 -0
  121. package/dist/motion.d.ts.map +1 -0
  122. package/dist/motion.js +80 -0
  123. package/dist/motion.js.map +1 -0
  124. package/dist/navigation.d.ts +100 -0
  125. package/dist/navigation.d.ts.map +1 -0
  126. package/dist/navigation.js +154 -0
  127. package/dist/navigation.js.map +1 -0
  128. package/dist/northstar/BriefForm.d.ts +23 -0
  129. package/dist/northstar/BriefForm.d.ts.map +1 -0
  130. package/dist/northstar/BriefForm.js +40 -0
  131. package/dist/northstar/BriefForm.js.map +1 -0
  132. package/dist/northstar/ExportMenu.d.ts +16 -0
  133. package/dist/northstar/ExportMenu.d.ts.map +1 -0
  134. package/dist/northstar/ExportMenu.js +11 -0
  135. package/dist/northstar/ExportMenu.js.map +1 -0
  136. package/dist/northstar/PopulationPanel.d.ts +30 -0
  137. package/dist/northstar/PopulationPanel.d.ts.map +1 -0
  138. package/dist/northstar/PopulationPanel.js +18 -0
  139. package/dist/northstar/PopulationPanel.js.map +1 -0
  140. package/dist/northstar/ResearchBuilder.d.ts +26 -0
  141. package/dist/northstar/ResearchBuilder.d.ts.map +1 -0
  142. package/dist/northstar/ResearchBuilder.js +81 -0
  143. package/dist/northstar/ResearchBuilder.js.map +1 -0
  144. package/dist/northstar/ResponsesView.d.ts +20 -0
  145. package/dist/northstar/ResponsesView.d.ts.map +1 -0
  146. package/dist/northstar/ResponsesView.js +42 -0
  147. package/dist/northstar/ResponsesView.js.map +1 -0
  148. package/dist/northstar/Run.d.ts +37 -0
  149. package/dist/northstar/Run.d.ts.map +1 -0
  150. package/dist/northstar/Run.js +32 -0
  151. package/dist/northstar/Run.js.map +1 -0
  152. package/dist/northstar/StudyShell.d.ts +50 -0
  153. package/dist/northstar/StudyShell.d.ts.map +1 -0
  154. package/dist/northstar/StudyShell.js +18 -0
  155. package/dist/northstar/StudyShell.js.map +1 -0
  156. package/dist/northstar/StudyStatus.d.ts +17 -0
  157. package/dist/northstar/StudyStatus.d.ts.map +1 -0
  158. package/dist/northstar/StudyStatus.js +26 -0
  159. package/dist/northstar/StudyStatus.js.map +1 -0
  160. package/dist/northstar/index.d.ts +10 -0
  161. package/dist/northstar/index.d.ts.map +1 -0
  162. package/dist/northstar/index.js +10 -0
  163. package/dist/northstar/index.js.map +1 -0
  164. package/dist/northstar/messages.d.ts +84 -0
  165. package/dist/northstar/messages.d.ts.map +1 -0
  166. package/dist/northstar/messages.js +107 -0
  167. package/dist/northstar/messages.js.map +1 -0
  168. package/dist/overlays.d.ts +136 -0
  169. package/dist/overlays.d.ts.map +1 -0
  170. package/dist/overlays.js +447 -0
  171. package/dist/overlays.js.map +1 -0
  172. package/dist/provider.d.ts +82 -0
  173. package/dist/provider.d.ts.map +1 -0
  174. package/dist/provider.js +128 -0
  175. package/dist/provider.js.map +1 -0
  176. package/dist/styles.css +2033 -0
  177. package/dist/surface.d.ts +58 -0
  178. package/dist/surface.d.ts.map +1 -0
  179. package/dist/surface.js +39 -0
  180. package/dist/surface.js.map +1 -0
  181. package/package.json +81 -3
  182. package/README.md +0 -3
@@ -0,0 +1,100 @@
1
+ import type { Material } from './provider.js';
2
+ import { type Expand } from './internal/expand.js';
3
+ /** `line` (default): a glacier underline that slides between tabs. `glass` / `solid`: a sliding pill behind the label. */
4
+ export type TabsIndicator = 'line' | Material;
5
+ export interface TabsRootProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'> {
6
+ value?: string;
7
+ defaultValue?: string;
8
+ onValueChange?: (value: string) => void;
9
+ orientation?: 'horizontal' | 'vertical';
10
+ /** How the selected tab is marked. Default `line`. */
11
+ indicator?: TabsIndicator;
12
+ /** Cross-fade panels with the View Transitions API where supported. Default false. */
13
+ transition?: boolean;
14
+ /** Sliding-pill tabs (`glass`, `solid`) are pills by default; `rounded` opts out to tight corners. */
15
+ shape?: 'pill' | 'rounded';
16
+ }
17
+ declare function TabsRoot({ value, defaultValue, onValueChange, orientation, indicator, transition, shape, className, ...rest }: TabsRootProps): import("react/jsx-runtime").JSX.Element;
18
+ declare function TabsList({ className, onKeyDown, children, ...rest }: React.HTMLAttributes<HTMLDivElement> & {
19
+ label?: string;
20
+ }): import("react/jsx-runtime").JSX.Element;
21
+ export interface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
22
+ value: string;
23
+ /** Leading icon (decorative). */
24
+ icon?: React.ReactNode;
25
+ /**
26
+ * Icon tabs: with `icon`, `true` shows the icon and eases the label open on
27
+ * hover, keyboard focus and while selected (always on touch). `always`
28
+ * keeps it open. Default false.
29
+ */
30
+ expand?: Expand;
31
+ }
32
+ declare function TabsTrigger({ value, icon, expand, className, onClick, children, ...rest }: TabsTriggerProps): import("react/jsx-runtime").JSX.Element;
33
+ export interface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {
34
+ value: string;
35
+ /** Keep the panel mounted when hidden. */
36
+ forceMount?: boolean;
37
+ }
38
+ declare function TabsContent({ value, forceMount, className, ...rest }: TabsContentProps): import("react/jsx-runtime").JSX.Element | null;
39
+ /** Tabs with automatic activation: arrow keys move and select, Home/End jump. */
40
+ export declare const Tabs: {
41
+ Root: typeof TabsRoot;
42
+ List: typeof TabsList;
43
+ Trigger: typeof TabsTrigger;
44
+ Content: typeof TabsContent;
45
+ };
46
+ export interface BreadcrumbItem {
47
+ label: React.ReactNode;
48
+ href?: string;
49
+ /** Shown in place of the label while the crumb is collapsed. */
50
+ icon?: React.ReactNode;
51
+ }
52
+ export interface BreadcrumbsProps extends React.HTMLAttributes<HTMLElement> {
53
+ items: BreadcrumbItem[];
54
+ /**
55
+ * Collapse the crumbs between the first and the current one to their icon
56
+ * (or an ellipsis); each eases open to its full label on hover and keyboard
57
+ * focus, and every crumb opens while focus is in the trail. The full labels
58
+ * stay in the accessibility tree. Default false.
59
+ */
60
+ collapse?: boolean;
61
+ }
62
+ export declare function Breadcrumbs({ items, collapse, className, ...rest }: BreadcrumbsProps): import("react/jsx-runtime").JSX.Element;
63
+ export interface PaginationProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
64
+ pageCount: number;
65
+ page?: number;
66
+ defaultPage?: number;
67
+ onPageChange?: (page: number) => void;
68
+ /** Pages shown either side of the current one. */
69
+ siblings?: number;
70
+ /**
71
+ * Previous and next are icon-first: the arrow shows and "Previous page" /
72
+ * "Next page" ease open on hover and focus. `always` keeps the words, false
73
+ * keeps arrows only (named by aria-label). Default true.
74
+ */
75
+ expand?: Expand;
76
+ /** Page and step buttons are pills (single pages are circles); `rounded` opts out. */
77
+ shape?: 'pill' | 'rounded';
78
+ }
79
+ export declare function Pagination({ pageCount, page, defaultPage, onPageChange, siblings, expand, shape, className, ...rest }: PaginationProps): import("react/jsx-runtime").JSX.Element;
80
+ export interface SidebarProps extends React.HTMLAttributes<HTMLElement> {
81
+ label?: string;
82
+ /** Icon rail: items show their icon and the rail eases open to full labels on hover and focus. */
83
+ collapsed?: boolean;
84
+ header?: React.ReactNode;
85
+ footer?: React.ReactNode;
86
+ }
87
+ export declare function Sidebar({ label, collapsed, header, footer, className, children, ...rest }: SidebarProps): import("react/jsx-runtime").JSX.Element;
88
+ export interface SidebarSectionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
89
+ title?: React.ReactNode;
90
+ }
91
+ export declare function SidebarSection({ title, className, children, ...rest }: SidebarSectionProps): import("react/jsx-runtime").JSX.Element;
92
+ export interface SidebarItemProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
93
+ icon?: React.ReactNode;
94
+ active?: boolean;
95
+ /** Trailing count or badge. */
96
+ meta?: React.ReactNode;
97
+ }
98
+ export declare function SidebarItem({ icon, active, meta, className, children, ...rest }: SidebarItemProps): import("react/jsx-runtime").JSX.Element;
99
+ export {};
100
+ //# sourceMappingURL=navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../src/navigation.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,154 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { createContext, useContext, useEffect, useId, useLayoutEffect, useRef } from 'react';
4
+ import { useNorthstar } from './provider.js';
5
+ import { rovingKeyDown } from './internal/layers.js';
6
+ import { withViewTransition } from './motion.js';
7
+ import { cx, useControllable } from './internal/util.js';
8
+ import { ChevronLeft, ChevronRight } from './internal/icons.js';
9
+ import { ExpandIcon, ExpandLabel, expandHost } from './internal/expand.js';
10
+ const useIsoLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
11
+ const TabsContext = createContext(null);
12
+ function useTabs(name) {
13
+ const v = useContext(TabsContext);
14
+ if (!v)
15
+ throw new Error(`<${name}> must be used inside <Tabs.Root>`);
16
+ return v;
17
+ }
18
+ function TabsRoot({ value, defaultValue, onValueChange, orientation = 'horizontal', indicator = 'line', transition = false, shape = 'pill', className, ...rest }) {
19
+ const [v, setRaw] = useControllable(value, defaultValue ?? '', onValueChange);
20
+ const root = useRef(null);
21
+ const setV = (next) => {
22
+ if (next === v)
23
+ return;
24
+ if (transition)
25
+ withViewTransition(() => setRaw(next), root.current?.querySelector(':scope > .ns-tabs__content, :scope .ns-tabs__content'));
26
+ else
27
+ setRaw(next);
28
+ };
29
+ const baseId = `ns-tabs-${useId().replace(/:/g, '')}`;
30
+ return (_jsx(TabsContext.Provider, { value: { value: v, setValue: setV, baseId, orientation, indicator }, children: _jsx("div", { ...rest, ref: root, className: cx('ns-tabs', `ns-tabs--${orientation}`, transition && 'ns-tabs--vt', indicator !== 'line' && 'ns-tabs--pill', indicator === 'glass' && 'ns-tabs--glass', shape === 'rounded' && 'ns-tabs--rounded', className) }) }));
31
+ }
32
+ /**
33
+ * Measures the selected tab and moves the indicator with a transform written
34
+ * straight to the element: no re-render, and a spring transition in CSS. Until
35
+ * it has measured (server HTML, no layout) each selected tab draws its own mark.
36
+ */
37
+ function useIndicator(list, mark, value) {
38
+ useIsoLayoutEffect(() => {
39
+ const el = list.current;
40
+ const ind = mark.current;
41
+ if (!el || !ind)
42
+ return;
43
+ let frame = 0;
44
+ const place = () => {
45
+ const tab = el.querySelector('[role="tab"][aria-selected="true"]');
46
+ if (!tab || tab.offsetWidth === 0) {
47
+ el.removeAttribute('data-indicator');
48
+ return;
49
+ }
50
+ ind.style.width = `${tab.offsetWidth}px`;
51
+ ind.style.height = `${tab.offsetHeight}px`;
52
+ ind.style.transform = `translate(${tab.offsetLeft}px, ${tab.offsetTop}px)`;
53
+ // The first placement jumps into position; later ones slide.
54
+ if (!el.hasAttribute('data-indicator')) {
55
+ el.setAttribute('data-indicator', 'placed');
56
+ frame = requestAnimationFrame(() => el.setAttribute('data-indicator', 'ready'));
57
+ }
58
+ };
59
+ place();
60
+ const ro = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(place);
61
+ ro?.observe(el);
62
+ // Icon-first tabs change width as their labels ease open; follow them.
63
+ el.querySelectorAll('[role="tab"]').forEach((t) => ro?.observe(t));
64
+ return () => {
65
+ ro?.disconnect();
66
+ cancelAnimationFrame(frame);
67
+ };
68
+ }, [value]);
69
+ }
70
+ function TabsList({ className, onKeyDown, children, ...rest }) {
71
+ const ctx = useTabs('Tabs.List');
72
+ const { label, ...props } = rest;
73
+ const list = useRef(null);
74
+ const mark = useRef(null);
75
+ useIndicator(list, mark, ctx.value);
76
+ return (_jsxs("div", { role: "tablist", "aria-label": label, "aria-orientation": ctx.orientation, ...props, ref: list, className: cx('ns-tabs__list', className), onKeyDown: (e) => {
77
+ onKeyDown?.(e);
78
+ const t = rovingKeyDown(e, '[role="tab"]', ctx.orientation);
79
+ const v = t?.getAttribute('data-value');
80
+ if (v)
81
+ ctx.setValue(v);
82
+ }, children: [_jsx("span", { ref: mark, className: "ns-tabs__indicator", "aria-hidden": "true" }), children] }));
83
+ }
84
+ function TabsTrigger({ value, icon, expand = false, className, onClick, children, ...rest }) {
85
+ const ctx = useTabs('Tabs.Trigger');
86
+ const selected = ctx.value === value;
87
+ const hasIcon = icon !== undefined && icon !== null && icon !== false;
88
+ const host = hasIcon ? expandHost(expand) : {};
89
+ return (_jsxs("button", { type: "button", role: "tab", id: `${ctx.baseId}-tab-${value}`, "aria-selected": selected, "aria-controls": `${ctx.baseId}-panel-${value}`, tabIndex: selected ? 0 : -1, "data-value": value, "data-expand": host['data-expand'], ...rest, className: cx('ns-tabs__trigger', hasIcon && 'ns-tabs__trigger--icon', host.className, className), onClick: (e) => {
90
+ onClick?.(e);
91
+ ctx.setValue(value);
92
+ }, children: [hasIcon && _jsx(ExpandIcon, { className: "ns-tabs__icon", children: icon }), host.className ? _jsx(ExpandLabel, { className: "ns-tabs__label", children: children }) : children] }));
93
+ }
94
+ function TabsContent({ value, forceMount = false, className, ...rest }) {
95
+ const ctx = useTabs('Tabs.Content');
96
+ const selected = ctx.value === value;
97
+ if (!selected && !forceMount)
98
+ return null;
99
+ return (_jsx("div", { role: "tabpanel", id: `${ctx.baseId}-panel-${value}`, "aria-labelledby": `${ctx.baseId}-tab-${value}`, tabIndex: 0, hidden: !selected, ...rest, className: cx('ns-tabs__content', className) }));
100
+ }
101
+ /** Tabs with automatic activation: arrow keys move and select, Home/End jump. */
102
+ export const Tabs = { Root: TabsRoot, List: TabsList, Trigger: TabsTrigger, Content: TabsContent };
103
+ export function Breadcrumbs({ items, collapse = false, className, ...rest }) {
104
+ const { messages } = useNorthstar();
105
+ return (_jsx("nav", { "aria-label": messages.breadcrumbs, ...rest, className: cx('ns-breadcrumbs', collapse && 'ns-breadcrumbs--collapse', className), children: _jsx("ol", { children: items.map((item, i) => {
106
+ const last = i === items.length - 1;
107
+ const folded = collapse && i > 0 && !last;
108
+ const body = folded ? (_jsxs(_Fragment, { children: [_jsx(ExpandIcon, { className: "ns-breadcrumbs__icon", children: item.icon ?? _jsx("span", { className: "ns-breadcrumbs__more", children: "\u2026" }) }), _jsx(ExpandLabel, { children: item.label })] })) : (item.label);
109
+ const host = folded ? expandHost(true) : {};
110
+ return (_jsxs("li", { className: host.className, "data-expand": host['data-expand'], children: [last || !item.href ? (_jsx("span", { "aria-current": last ? 'page' : undefined, children: body })) : (_jsx("a", { href: item.href, children: body })), !last && (_jsx("span", { className: "ns-breadcrumbs__sep", "aria-hidden": "true", children: "/" }))] }, i));
111
+ }) }) }));
112
+ }
113
+ function range(page, count, siblings) {
114
+ const out = [];
115
+ const from = Math.max(2, page - siblings);
116
+ const to = Math.min(count - 1, page + siblings);
117
+ out.push(1);
118
+ if (from > 2)
119
+ out.push('gap');
120
+ for (let i = from; i <= to; i++)
121
+ out.push(i);
122
+ if (to < count - 1)
123
+ out.push('gap');
124
+ if (count > 1)
125
+ out.push(count);
126
+ return out;
127
+ }
128
+ export function Pagination({ pageCount, page, defaultPage, onPageChange, siblings = 1, expand = true, shape = 'pill', className, ...rest }) {
129
+ const { messages } = useNorthstar();
130
+ const [p, setP] = useControllable(page, defaultPage ?? 1, onPageChange);
131
+ const go = (n) => setP(Math.min(pageCount, Math.max(1, n)));
132
+ return (_jsxs("nav", { "aria-label": messages.pagination, ...rest, className: cx('ns-pagination', shape === 'rounded' && 'ns-pagination--rounded', className), children: [_jsx(PageStep, { expand: expand, label: messages.previousPage, disabled: p <= 1, onClick: () => go(p - 1), children: _jsx(ChevronLeft, {}) }), _jsx("ul", { children: range(p, pageCount, siblings).map((n, i) => n === 'gap' ? (_jsx("li", { className: "ns-pagination__gap", "aria-hidden": "true", children: "\u2026" }, `gap-${i}`)) : (_jsx("li", { children: _jsx("button", { type: "button", className: "ns-button ns-button--ghost ns-size-sm ns-pagination__page", "aria-label": messages.page(n), "aria-current": n === p ? 'page' : undefined, onClick: () => go(n), children: n }) }, n))) }), _jsx(PageStep, { expand: expand, end: true, label: messages.nextPage, disabled: p >= pageCount, onClick: () => go(p + 1), children: _jsx(ChevronRight, {}) })] }));
133
+ }
134
+ function PageStep({ expand, end = false, label, disabled, onClick, children }) {
135
+ if (!expand) {
136
+ return (_jsx("button", { type: "button", className: "ns-button ns-button--ghost ns-size-sm ns-icon-button", "aria-label": label, disabled: disabled, onClick: onClick, children: children }));
137
+ }
138
+ const host = expandHost(expand);
139
+ const icon = _jsx(ExpandIcon, { children: children });
140
+ const text = _jsx(ExpandLabel, { side: end ? 'end' : 'start', children: label });
141
+ return (_jsxs("button", { type: "button", className: cx('ns-button ns-button--ghost ns-size-sm ns-icon-button ns-icon-button--expand ns-button--expand ns-pagination__step', host.className), "data-expand": host['data-expand'], disabled: disabled, onClick: onClick, children: [end ? text : icon, end ? icon : text] }));
142
+ }
143
+ export function Sidebar({ label, collapsed = false, header, footer, className, children, ...rest }) {
144
+ const { messages } = useNorthstar();
145
+ return (_jsxs("nav", { "aria-label": label ?? messages.sidebar, ...rest, className: cx('ns-sidebar', collapsed && 'ns-sidebar--collapsed', className), children: [header && _jsx("div", { className: "ns-sidebar__header", children: header }), _jsx("div", { className: "ns-sidebar__body", children: children }), footer && _jsx("div", { className: "ns-sidebar__footer", children: footer })] }));
146
+ }
147
+ export function SidebarSection({ title, className, children, ...rest }) {
148
+ const id = useId();
149
+ return (_jsxs("div", { role: "group", "aria-labelledby": title ? id : undefined, ...rest, className: cx('ns-sidebar__section', className), children: [title && (_jsx("div", { id: id, className: "ns-sidebar__title", children: title })), _jsx("ul", { children: children })] }));
150
+ }
151
+ export function SidebarItem({ icon, active = false, meta, className, children, ...rest }) {
152
+ return (_jsx("li", { children: _jsxs("a", { "aria-current": active ? 'page' : undefined, ...rest, className: cx('ns-sidebar__item', className), children: [icon && (_jsx("span", { className: "ns-sidebar__icon", "aria-hidden": "true", children: icon })), _jsx(ExpandLabel, { className: "ns-sidebar__text", children: children }), meta !== undefined && _jsx("span", { className: "ns-sidebar__meta", children: meta })] }) }));
153
+ }
154
+ //# sourceMappingURL=navigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../src/navigation.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type WithMessages } from './messages.js';
3
+ export interface BriefValue {
4
+ title: string;
5
+ /** The decision the study informs. */
6
+ decision: string;
7
+ objectives: string[];
8
+ }
9
+ export interface BriefFormProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'>, WithMessages {
10
+ value?: BriefValue;
11
+ defaultValue?: BriefValue;
12
+ onValueChange?: (value: BriefValue) => void;
13
+ /** Most objectives a study may carry. Default 5. */
14
+ maxObjectives?: number;
15
+ /** Per-objective meta, e.g. "3 items". */
16
+ objectiveMeta?: (index: number) => ReactNode;
17
+ /** Shown above the objectives (a template picker, say). */
18
+ toolbar?: ReactNode;
19
+ readOnly?: boolean;
20
+ }
21
+ /** The Brief tab: study name, the decision it informs, and its objectives. */
22
+ export declare function BriefForm({ value, defaultValue, onValueChange, maxObjectives, objectiveMeta, toolbar, readOnly, messages, className, ...rest }: BriefFormProps): import("react/jsx-runtime").JSX.Element;
23
+ //# sourceMappingURL=BriefForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BriefForm.d.ts","sourceRoot":"","sources":["../../src/northstar/BriefForm.tsx"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEjE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,EAAE,YAAY;IAC3H,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IAC7C,2DAA2D;IAC3D,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAID,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,EACxB,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,aAAiB,EAAE,aAAa,EAAE,OAAO,EAAE,QAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAC9H,EAAE,cAAc,2CA8FhB"}
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId, useRef } from 'react';
4
+ import { Button } from '../actions.js';
5
+ import { cx, useControllable } from '../internal/util.js';
6
+ import { studyMessages } from './messages.js';
7
+ const EMPTY = { title: '', decision: '', objectives: [] };
8
+ /** The Brief tab: study name, the decision it informs, and its objectives. */
9
+ export function BriefForm({ value, defaultValue, onValueChange, maxObjectives = 5, objectiveMeta, toolbar, readOnly = false, messages, className, ...rest }) {
10
+ const m = studyMessages(messages);
11
+ const [v, setV] = useControllable(value, defaultValue ?? EMPTY, onValueChange);
12
+ const headingId = `ns-brief-${useId().replace(/:/g, '')}`;
13
+ const list = useRef(null);
14
+ const patch = (p) => setV({ ...v, ...p });
15
+ const focusRow = (i) => requestAnimationFrame(() => list.current?.querySelectorAll('input')[i]?.focus());
16
+ const add = () => {
17
+ if (v.objectives.length >= maxObjectives)
18
+ return;
19
+ patch({ objectives: [...v.objectives, ''] });
20
+ focusRow(v.objectives.length);
21
+ };
22
+ const remove = (i) => {
23
+ patch({ objectives: v.objectives.filter((_, j) => j !== i) });
24
+ focusRow(Math.max(0, i - 1));
25
+ };
26
+ const full = v.objectives.length >= maxObjectives;
27
+ return (_jsxs("div", { ...rest, className: cx('ns-brief', className), children: [_jsxs("div", { className: "ns-brief__head", children: [_jsx("input", { className: "ns-brief__title", "aria-label": m.studyName, value: v.title, readOnly: readOnly, onChange: (e) => patch({ title: e.target.value }) }), _jsx("textarea", { className: "ns-brief__decision", rows: 2, "aria-label": m.decision, placeholder: m.decisionPlaceholder, value: v.decision, readOnly: readOnly, onChange: (e) => patch({ decision: e.target.value }) })] }), toolbar && _jsx("div", { className: "ns-brief__toolbar", children: toolbar }), _jsxs("section", { className: "ns-study-panel", "aria-labelledby": headingId, children: [_jsxs("div", { className: "ns-study-panel__head", children: [_jsx("h2", { id: headingId, className: "ns-study-panel__title", children: m.objectives }), _jsx("span", { className: "ns-study-hint", children: m.objectiveCount(v.objectives.length, maxObjectives) }), !readOnly && (_jsx(Button, { variant: "ghost", size: "sm", className: "ns-study-panel__action", onClick: add, disabled: full, children: m.addObjective }))] }), _jsxs("div", { ref: list, role: "list", children: [v.objectives.map((o, i) => (_jsxs("div", { role: "listitem", className: "ns-study-row", children: [_jsxs("span", { className: "ns-study-id", "aria-hidden": "true", children: ["O", i + 1] }), _jsx("input", { className: "ns-study-row__input", "aria-label": m.objectiveLabel(i), value: o, readOnly: readOnly, onChange: (e) => patch({ objectives: v.objectives.map((x, j) => (j === i ? e.target.value : x)) }), onKeyDown: (e) => {
28
+ if (readOnly)
29
+ return;
30
+ if (e.key === 'Enter') {
31
+ e.preventDefault();
32
+ add();
33
+ }
34
+ else if (e.key === 'Backspace' && o === '' && v.objectives.length > 0) {
35
+ e.preventDefault();
36
+ remove(i);
37
+ }
38
+ } }), objectiveMeta && _jsx("span", { className: "ns-tag", children: objectiveMeta(i) }), !readOnly && (_jsx("button", { type: "button", className: "ns-study-icon-button", "aria-label": m.removeObjective(i), onClick: () => remove(i), children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: _jsx("path", { d: "M3 3l6 6M9 3l-6 6" }) }) }))] }, i))), !readOnly && !full && (_jsxs("div", { role: "listitem", className: "ns-study-row", children: [_jsxs("span", { className: "ns-study-id", "aria-hidden": "true", children: ["O", v.objectives.length + 1] }), _jsx("button", { type: "button", className: "ns-study-row__ghost", onClick: add, children: m.objectivePlaceholder })] }))] })] }), _jsx("span", { className: "ns-study-hint", children: m.objectivesHint })] }));
39
+ }
40
+ //# sourceMappingURL=BriefForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BriefForm.js","sourceRoot":"","sources":["../../src/northstar/BriefForm.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type WithMessages } from './messages.js';
2
+ export type ExportFormat = 'pdf' | 'spec' | 'csv';
3
+ export interface ExportMenuProps extends WithMessages {
4
+ onExport: (format: ExportFormat) => void;
5
+ /** Which formats to offer, in order. Default all three. */
6
+ formats?: ExportFormat[];
7
+ /** Formats shown but not available yet. */
8
+ disabledFormats?: ExportFormat[];
9
+ disabled?: boolean;
10
+ className?: string;
11
+ /** Icon-first trigger: the export icon shows and "Export" eases open on hover, focus and while open. `always` keeps it. Default false. */
12
+ expand?: boolean | 'always';
13
+ }
14
+ /** Export a finished study: PDF report, report spec, or responses as CSV. */
15
+ export declare function ExportMenu({ onExport, formats, disabledFormats, disabled, className, expand, messages }: ExportMenuProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=ExportMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExportMenu.d.ts","sourceRoot":"","sources":["../../src/northstar/ExportMenu.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AAElD,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IACzC,2DAA2D;IAC3D,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,2CAA2C;IAC3C,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0IAA0I;IAC1I,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAgC,EAAE,eAAoB,EAAE,QAAgB,EAAE,SAAS,EAAE,MAAc,EAAE,QAAQ,EAAE,EAAE,eAAe,2CAqBtK"}
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Icon } from '@northstar-js/icons';
4
+ import { Menu } from '../overlays.js';
5
+ import { studyMessages } from './messages.js';
6
+ /** Export a finished study: PDF report, report spec, or responses as CSV. */
7
+ export function ExportMenu({ onExport, formats = ['pdf', 'spec', 'csv'], disabledFormats = [], disabled = false, className, expand = false, messages }) {
8
+ const m = studyMessages(messages);
9
+ return (_jsxs(Menu.Root, { children: [_jsx(Menu.Trigger, { className: ['ns-button ns-button--secondary ns-size-md ns-export-menu', className].filter(Boolean).join(' '), disabled: disabled, icon: _jsx(Icon, { name: "export", size: 14 }), expand: expand, children: m.export }), _jsx(Menu.Content, { align: "end", children: formats.map((f) => (_jsx(Menu.Item, { onSelect: () => onExport(f), disabled: disabledFormats.includes(f), children: m.exportFormats[f] }, f))) })] }));
10
+ }
11
+ //# sourceMappingURL=ExportMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExportMenu.js","sourceRoot":"","sources":["../../src/northstar/ExportMenu.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,aAAa,EAAqB,MAAM,eAAe,CAAC;AAgBjE,6EAA6E;AAC7E,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,EAAE,EAAE,QAAQ,GAAG,KAAK,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,EAAmB;IACrK,MAAM,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAClC,OAAO,CACL,MAAC,IAAI,CAAC,IAAI,eACR,KAAC,IAAI,CAAC,OAAO,IACX,SAAS,EAAE,CAAC,0DAA0D,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAC5G,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,KAAC,IAAI,IAAC,IAAI,EAAC,QAAQ,EAAC,IAAI,EAAE,EAAE,GAAI,EACtC,MAAM,EAAE,MAAM,YAEb,CAAC,CAAC,MAAM,GACI,EACf,KAAC,IAAI,CAAC,OAAO,IAAC,KAAK,EAAC,KAAK,YACtB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAClB,KAAC,IAAI,CAAC,IAAI,IAAS,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,YAClF,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IADL,CAAC,CAEL,CACb,CAAC,GACW,IACL,CACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { PopulationRef } from '@northstar-js/contracts';
3
+ import { type CompositionRow } from '@northstar-js/charts';
4
+ import { type WithMessages } from './messages.js';
5
+ export interface CompositionGroup {
6
+ /** Dimension name, e.g. "Age". */
7
+ label: string;
8
+ rows: CompositionRow[];
9
+ }
10
+ export interface PopulationPanelProps extends React.HTMLAttributes<HTMLDivElement>, WithMessages {
11
+ /** The study's one population. */
12
+ population: PopulationRef;
13
+ /** Margins (and panel shares once built), one group per dimension. Empty shows the empty state. */
14
+ composition?: CompositionGroup[];
15
+ /** Sub-heading of the composition panel, e.g. which margins it is raked to. */
16
+ compositionNote?: ReactNode;
17
+ /** Sentence under the composition panel. */
18
+ caption?: ReactNode;
19
+ onSizeChange?: (size: number | null) => void;
20
+ onSeedChange?: (seed: number | null) => void;
21
+ onRebuild?: () => void;
22
+ /** Locks size, seed and rebuild (after a run). */
23
+ readOnly?: boolean;
24
+ /** Width of each composition chart. Default 320. */
25
+ chartWidth?: number;
26
+ locale?: string;
27
+ }
28
+ /** The Population tab: market status, size and seed, and the composition against published margins. */
29
+ export declare function PopulationPanel({ population, composition, compositionNote, caption, onSizeChange, onSeedChange, onRebuild, readOnly, chartWidth, locale, messages, className, ...rest }: PopulationPanelProps): import("react/jsx-runtime").JSX.Element;
30
+ //# sourceMappingURL=PopulationPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PopulationPanel.d.ts","sourceRoot":"","sources":["../../src/northstar/PopulationPanel.tsx"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAMxE,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,YAAY;IAC9F,kCAAkC;IAClC,UAAU,EAAE,aAAa,CAAC;IAC1B,mGAAmG;IACnG,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,+EAA+E;IAC/E,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,4CAA4C;IAC5C,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,uGAAuG;AACvG,wBAAgB,eAAe,CAAC,EAC9B,UAAU,EAAE,WAAgB,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,QAAgB,EAC/G,UAAgB,EAAE,MAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAC9D,EAAE,oBAAoB,2CAoEtB"}
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId } from 'react';
4
+ import { Composition } from '@northstar-js/charts';
5
+ import { MarketStatus } from '@northstar-js/maps';
6
+ import { Button } from '../actions.js';
7
+ import { NumberInput } from '../forms.js';
8
+ import { EmptyPopulation } from '../illustrations/index.js';
9
+ import { cx } from '../internal/util.js';
10
+ import { studyMessages } from './messages.js';
11
+ /** The Population tab: market status, size and seed, and the composition against published margins. */
12
+ export function PopulationPanel({ population, composition = [], compositionNote, caption, onSizeChange, onSeedChange, onRebuild, readOnly = false, chartWidth = 320, locale = 'en', messages, className, ...rest }) {
13
+ const m = studyMessages(messages);
14
+ const id = useId().replace(/:/g, '');
15
+ const sizeId = `ns-pop-size-${id}`, seedId = `ns-pop-seed-${id}`, headId = `ns-pop-comp-${id}`;
16
+ return (_jsxs("div", { ...rest, className: cx('ns-population', className), children: [_jsxs("div", { className: "ns-population__controls", children: [_jsxs("span", { className: "ns-population__market", children: [_jsx("span", { className: "ns-study-label", children: m.market }), _jsx(MarketStatus, { code: population.code, variant: "row" })] }), _jsx("span", { className: "ns-study-divider", "aria-hidden": "true" }), _jsx("label", { className: "ns-study-label", htmlFor: sizeId, children: m.size }), _jsx(NumberInput, { id: sizeId, size: "sm", min: 0, value: population.size, ...(onSizeChange ? { onValueChange: onSizeChange } : {}), disabled: readOnly, className: "ns-population__number" }), _jsx("label", { className: "ns-study-label", htmlFor: seedId, children: m.seed }), _jsx(NumberInput, { id: seedId, size: "sm", min: 0, value: population.seed ?? null, ...(onSeedChange ? { onValueChange: onSeedChange } : {}), disabled: readOnly, className: "ns-population__number" }), _jsx(Button, { size: "sm", onClick: onRebuild, disabled: readOnly || !onRebuild, children: m.rebuild }), _jsx("span", { className: "ns-study-hint", children: m.rebuildHint })] }), _jsxs("section", { className: "ns-study-panel", "aria-labelledby": headId, children: [_jsxs("div", { className: "ns-study-panel__head", children: [_jsx("h2", { id: headId, className: "ns-study-panel__title", children: m.composition }), compositionNote && _jsx("span", { className: "ns-study-hint", children: compositionNote }), population.label && _jsx("span", { className: "ns-study-hint ns-study-panel__end ns-study-mono", children: population.label })] }), composition.length === 0 ? (_jsxs("div", { className: "ns-study-empty", children: [_jsx(EmptyPopulation, {}), _jsx("p", { className: "ns-study-empty__title", children: m.emptyPopulationTitle }), _jsx("p", { className: "ns-study-hint", children: m.emptyPopulationBody })] })) : (_jsx("div", { className: "ns-population__grid", children: composition.map((g) => (_jsxs("div", { className: "ns-population__group", children: [_jsx("h3", { className: "ns-population__group-title", children: g.label }), _jsx(Composition, { margins: g.rows, title: g.label, width: chartWidth, locale: locale })] }, g.label))) }))] }), caption && _jsx("span", { className: "ns-study-hint", children: caption }), _jsxs("div", { className: "ns-study-callout", children: [_jsx("span", { className: "ns-tag ns-tone-signal", children: m.scope }), _jsx("span", { children: m.scopeBody })] })] }));
17
+ }
18
+ //# sourceMappingURL=PopulationPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PopulationPanel.js","sourceRoot":"","sources":["../../src/northstar/PopulationPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { ResearchItem } from '@northstar-js/contracts';
3
+ import { type WithMessages } from './messages.js';
4
+ export interface AnchorIssue {
5
+ /** Zero-based anchor index. */
6
+ anchor: number;
7
+ message: ReactNode;
8
+ }
9
+ export interface ResearchBuilderProps extends React.HTMLAttributes<HTMLDivElement>, WithMessages {
10
+ items?: ResearchItem[];
11
+ defaultItems?: ResearchItem[];
12
+ onItemsChange?: (items: ResearchItem[]) => void;
13
+ selectedKey?: string | null;
14
+ defaultSelectedKey?: string | null;
15
+ onSelectedKeyChange?: (key: string | null) => void;
16
+ /** Anchor-check results per item key. Items with issues are marked "Fix". */
17
+ anchorIssues?: Record<string, AnchorIssue[]>;
18
+ /** Makes a new item for "Add item". Defaults to an empty five-anchor Likert item. */
19
+ createItem?: (index: number) => ResearchItem;
20
+ /** Extra controls in the editor header (an objective picker, say). */
21
+ editorToolbar?: (item: ResearchItem) => ReactNode;
22
+ readOnly?: boolean;
23
+ }
24
+ /** The Research tab: the item list (add, reorder, remove) beside an editor for wording, type, format and anchors. */
25
+ export declare function ResearchBuilder({ items, defaultItems, onItemsChange, selectedKey, defaultSelectedKey, onSelectedKeyChange, anchorIssues, createItem, editorToolbar, readOnly, messages, className, ...rest }: ResearchBuilderProps): import("react/jsx-runtime").JSX.Element;
26
+ //# sourceMappingURL=ResearchBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResearchBuilder.d.ts","sourceRoot":"","sources":["../../src/northstar/ResearchBuilder.tsx"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAgB,YAAY,EAAkB,MAAM,yBAAyB,CAAC;AAM1F,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,SAAS,CAAC;CACpB;AAKD,MAAM,WAAW,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,YAAY;IAC9F,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,EAAE,CAAC;IAC9B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IAC7C,qFAAqF;IACrF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,YAAY,CAAC;IAC7C,sEAAsE;IACtE,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,SAAS,CAAC;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAMD,qHAAqH;AACrH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,YAAiB,EAC3G,UAAwB,EAAE,aAAa,EAAE,QAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EACxF,EAAE,oBAAoB,2CAgLtB"}
@@ -0,0 +1,81 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useId, useRef } from 'react';
4
+ import { Icon } from '@northstar-js/icons';
5
+ import { Button, IconButton } from '../actions.js';
6
+ import { Select } from '../forms.js';
7
+ import { EmptyResearch } from '../illustrations/index.js';
8
+ import { cx, useControllable } from '../internal/util.js';
9
+ import { studyMessages } from './messages.js';
10
+ const QUESTION_TYPES = ['mood_direction', 'consensus_trust', 'neutral_factual', 'concrete_habit', 'values_identity', 'intention_virtue'];
11
+ const FORMATS = ['likert', 'single_choice', 'multi_select', 'ranking', 'free_text', 'price_trial'];
12
+ function defaultItem(i) {
13
+ return { key: `item-${Date.now().toString(36)}-${i}`, question: '', type: 'mood_direction', format: 'likert', anchors: ['', '', '', '', ''] };
14
+ }
15
+ /** The Research tab: the item list (add, reorder, remove) beside an editor for wording, type, format and anchors. */
16
+ export function ResearchBuilder({ items, defaultItems, onItemsChange, selectedKey, defaultSelectedKey, onSelectedKeyChange, anchorIssues = {}, createItem = defaultItem, editorToolbar, readOnly = false, messages, className, ...rest }) {
17
+ const m = studyMessages(messages);
18
+ const uid = useId().replace(/:/g, '');
19
+ const [list, setList] = useControllable(items, defaultItems ?? [], onItemsChange);
20
+ const [sel, setSel] = useControllable(selectedKey, defaultSelectedKey ?? list[0]?.key ?? null, onSelectedKeyChange);
21
+ const listRef = useRef(null);
22
+ const index = list.findIndex((x) => x.key === sel);
23
+ const item = index >= 0 ? list[index] : undefined;
24
+ const focusItem = (key) => requestAnimationFrame(() => Array.from(listRef.current?.querySelectorAll('[data-key]') ?? []).find((el) => el.dataset.key === key)?.focus());
25
+ const update = (patch) => {
26
+ if (!item)
27
+ return;
28
+ setList(list.map((x) => (x.key === item.key ? { ...x, ...patch } : x)));
29
+ };
30
+ const move = (i, dir) => {
31
+ const j = i + dir;
32
+ if (j < 0 || j >= list.length)
33
+ return;
34
+ const next = list.slice();
35
+ const a = next[i], b = next[j];
36
+ next[i] = b;
37
+ next[j] = a;
38
+ setList(next);
39
+ focusItem(a.key);
40
+ };
41
+ const remove = (i) => {
42
+ const gone = list[i];
43
+ const next = list.filter((_, j) => j !== i);
44
+ setList(next);
45
+ if (gone.key === sel) {
46
+ const n = next[Math.min(i, next.length - 1)];
47
+ setSel(n?.key ?? null);
48
+ if (n)
49
+ focusItem(n.key);
50
+ }
51
+ };
52
+ const add = () => {
53
+ const n = createItem(list.length);
54
+ setList([...list, n]);
55
+ setSel(n.key);
56
+ focusItem(n.key);
57
+ };
58
+ const issues = item ? (anchorIssues[item.key] ?? []) : [];
59
+ const id = (i) => m.itemId(i);
60
+ return (_jsxs("div", { ...rest, className: cx('ns-research', className), children: [_jsxs("div", { className: "ns-research__list", children: [_jsxs("div", { className: "ns-research__list-head", children: [_jsx("span", { children: m.items }), _jsx("span", { className: "ns-study-mono", children: list.length }), !readOnly && (_jsx(Button, { size: "sm", className: "ns-study-panel__end", icon: _jsx(Icon, { name: "add", size: 14 }), onClick: add, children: m.addItem }))] }), list.length === 0 ? (_jsxs("div", { className: "ns-study-empty", children: [_jsx(EmptyResearch, {}), _jsx("p", { className: "ns-study-empty__title", children: m.emptyResearchTitle }), _jsx("p", { className: "ns-study-hint", children: m.emptyResearchBody })] })) : (_jsx("ol", { ref: listRef, className: "ns-research__items", "aria-label": m.items, children: list.map((x, i) => {
61
+ const fix = (anchorIssues[x.key]?.length ?? 0) > 0;
62
+ const on = x.key === sel;
63
+ return (_jsxs("li", { className: cx('ns-research__item', on && 'ns-research__item--on'), children: [_jsxs("button", { type: "button", className: "ns-research__select", "data-key": x.key, "aria-current": on || undefined, onClick: () => setSel(x.key), onKeyDown: (e) => {
64
+ if (readOnly || !e.altKey)
65
+ return;
66
+ if (e.key === 'ArrowUp') {
67
+ e.preventDefault();
68
+ move(i, -1);
69
+ }
70
+ if (e.key === 'ArrowDown') {
71
+ e.preventDefault();
72
+ move(i, 1);
73
+ }
74
+ }, children: [_jsx("span", { className: "ns-study-id", children: id(i) }), _jsx(Icon, { name: fix ? 'off-axis' : 'complete', size: 14, className: fix ? 'ns-study-signal' : 'ns-study-muted' }), _jsx("span", { className: "ns-research__q", children: x.question || '—' }), fix ? _jsx("span", { className: "ns-tag ns-tone-signal", children: m.needsFix }) : x.format && _jsx("span", { className: "ns-tag", children: m.formats[x.format] })] }), !readOnly && (_jsxs("span", { className: "ns-research__tools", children: [_jsx(IconButton, { size: "sm", variant: "ghost", expand: true, className: "ns-research__tool", label: m.moveUp(id(i)), disabled: i === 0, onClick: () => move(i, -1), icon: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: _jsx("path", { d: "M3 7.5 6 4.5 9 7.5" }) }) }), _jsx(IconButton, { size: "sm", variant: "ghost", expand: true, className: "ns-research__tool", label: m.moveDown(id(i)), disabled: i === list.length - 1, onClick: () => move(i, 1), icon: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: _jsx("path", { d: "M3 4.5 6 7.5 9 4.5" }) }) }), _jsx(IconButton, { size: "sm", variant: "ghost", expand: true, className: "ns-research__tool", label: m.removeItem(id(i)), onClick: () => remove(i), icon: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: _jsx("path", { d: "M3 3l6 6M9 3l-6 6" }) }) })] }))] }, x.key));
75
+ }) }))] }), _jsx("div", { className: "ns-research__editor", children: !item ? (_jsx("p", { className: "ns-study-hint", children: m.selectItem })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "ns-research__editor-head", children: [_jsx("span", { className: "ns-study-id", children: id(index) }), _jsx(Select, { size: "sm", "aria-label": m.questionType, value: item.type, disabled: readOnly, options: QUESTION_TYPES.map((t) => ({ value: t, label: m.questionTypes[t] })), onValueChange: (t) => update({ type: t }) }), _jsx(Select, { size: "sm", "aria-label": m.format, value: item.format ?? 'likert', disabled: readOnly, options: FORMATS.map((f) => ({ value: f, label: m.formats[f] })), onValueChange: (f) => update({ format: f }) }), editorToolbar?.(item)] }), _jsx("textarea", { className: "ns-research__wording", rows: 2, "aria-label": m.wording, value: item.question, readOnly: readOnly, onChange: (e) => update({ question: e.target.value }) }), item.anchors && (_jsxs("fieldset", { className: "ns-research__anchors", children: [_jsx("legend", { className: "ns-study-label", children: m.anchors }), item.anchors.map((a, i) => {
76
+ const issue = issues.find((x) => x.anchor === i);
77
+ const descId = `ns-anchor-${uid}-${i}`;
78
+ return (_jsxs("div", { className: "ns-research__anchor", children: [_jsx("span", { className: "ns-study-id", children: i + 1 }), _jsx("input", { className: cx('ns-research__anchor-input', issue && 'ns-invalid'), "aria-label": m.anchorLabel(i), "aria-invalid": issue ? true : undefined, "aria-describedby": issue ? descId : undefined, value: a, readOnly: readOnly, onChange: (e) => update({ anchors: item.anchors.map((y, j) => (j === i ? e.target.value : y)) }) }), _jsx(Icon, { name: issue ? 'off-axis' : 'validate', size: 14, title: issue ? m.anchorNeedsFix : m.anchorPasses, className: issue ? 'ns-study-signal' : 'ns-study-muted' })] }, i));
79
+ })] })), issues.map((x) => (_jsxs("div", { id: `ns-anchor-${uid}-${x.anchor}`, className: "ns-study-callout", children: [_jsx("span", { className: "ns-tag ns-tone-signal", children: m.anchorLabel(x.anchor) }), _jsx("span", { children: x.message })] }, x.anchor))), _jsx("span", { className: "ns-study-hint", children: m.anchorHint })] })) })] }));
80
+ }
81
+ //# sourceMappingURL=ResearchBuilder.js.map