@isahaq/kosh-ui 0.0.0-stage → 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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -2
  3. package/dist/api.d.ts +158 -0
  4. package/dist/api.d.ts.map +1 -0
  5. package/dist/api.js +216 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/app.d.ts +14 -0
  8. package/dist/app.d.ts.map +1 -0
  9. package/dist/app.js +355 -0
  10. package/dist/app.js.map +1 -0
  11. package/dist/components/primitives.d.ts +60 -0
  12. package/dist/components/primitives.d.ts.map +1 -0
  13. package/dist/components/primitives.js +105 -0
  14. package/dist/components/primitives.js.map +1 -0
  15. package/dist/context.d.ts +34 -0
  16. package/dist/context.d.ts.map +1 -0
  17. package/dist/context.js +58 -0
  18. package/dist/context.js.map +1 -0
  19. package/dist/i18n/index.d.ts +14 -0
  20. package/dist/i18n/index.d.ts.map +1 -0
  21. package/dist/i18n/index.js +43 -0
  22. package/dist/i18n/index.js.map +1 -0
  23. package/dist/i18n/messages.d.ts +104 -0
  24. package/dist/i18n/messages.d.ts.map +1 -0
  25. package/dist/i18n/messages.js +194 -0
  26. package/dist/i18n/messages.js.map +1 -0
  27. package/dist/index.d.ts +31 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +42 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/lib/cn.d.ts +4 -0
  32. package/dist/lib/cn.d.ts.map +1 -0
  33. package/dist/lib/cn.js +7 -0
  34. package/dist/lib/cn.js.map +1 -0
  35. package/dist/lib/format.d.ts +18 -0
  36. package/dist/lib/format.d.ts.map +1 -0
  37. package/dist/lib/format.js +48 -0
  38. package/dist/lib/format.js.map +1 -0
  39. package/dist/registry.d.ts +80 -0
  40. package/dist/registry.d.ts.map +1 -0
  41. package/dist/registry.js +57 -0
  42. package/dist/registry.js.map +1 -0
  43. package/dist/search/SearchBar.d.ts +19 -0
  44. package/dist/search/SearchBar.d.ts.map +1 -0
  45. package/dist/search/SearchBar.js +84 -0
  46. package/dist/search/SearchBar.js.map +1 -0
  47. package/dist/shell/Login.d.ts +7 -0
  48. package/dist/shell/Login.d.ts.map +1 -0
  49. package/dist/shell/Login.js +41 -0
  50. package/dist/shell/Login.js.map +1 -0
  51. package/dist/views/FormView.d.ts +5 -0
  52. package/dist/views/FormView.d.ts.map +1 -0
  53. package/dist/views/FormView.js +276 -0
  54. package/dist/views/FormView.js.map +1 -0
  55. package/dist/views/KanbanView.d.ts +11 -0
  56. package/dist/views/KanbanView.d.ts.map +1 -0
  57. package/dist/views/KanbanView.js +156 -0
  58. package/dist/views/KanbanView.js.map +1 -0
  59. package/dist/views/ListView.d.ts +5 -0
  60. package/dist/views/ListView.d.ts.map +1 -0
  61. package/dist/views/ListView.js +227 -0
  62. package/dist/views/ListView.js.map +1 -0
  63. package/dist/views/widgets.d.ts +15 -0
  64. package/dist/views/widgets.d.ts.map +1 -0
  65. package/dist/views/widgets.js +253 -0
  66. package/dist/views/widgets.js.map +1 -0
  67. package/package.json +75 -3
  68. package/src/styles.css +101 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Locale-aware formatting (RFC 0007 i18n): numbers, exact decimals (strings, never floats), dates and datetimes from
3
+ * the user's language and time zone, through `Intl`. Bangla can use Bengali digits (`bn` with `nu-beng`).
4
+ */
5
+ /** Kosh language codes (`bn_BD`) → BCP 47 (`bn-BD`). */
6
+ export function bcp47(lang) {
7
+ return lang.replace('_', '-');
8
+ }
9
+ export function createFormatter(lang, tz, options = {}) {
10
+ const base = bcp47(lang);
11
+ // Bangla defaults to Bengali digits in ICU; RFC 0007 makes them a choice (Latin digits unless asked).
12
+ const locale = base.startsWith('bn')
13
+ ? `${base}-u-nu-${options.nativeDigits === true ? 'beng' : 'latn'}`
14
+ : base;
15
+ const integer = new Intl.NumberFormat(locale, { maximumFractionDigits: 0 });
16
+ const digits = new Intl.NumberFormat(locale, { useGrouping: false });
17
+ const separator = new Intl.NumberFormat(locale).formatToParts(1.5).find((p) => p.type === 'decimal')?.value ??
18
+ '.';
19
+ const date = new Intl.DateTimeFormat(locale, { dateStyle: 'medium', timeZone: 'UTC' });
20
+ const datetime = new Intl.DateTimeFormat(locale, {
21
+ dateStyle: 'medium',
22
+ timeStyle: 'short',
23
+ timeZone: tz,
24
+ });
25
+ return {
26
+ locale,
27
+ number: (value) => value === null || value === undefined ? '' : new Intl.NumberFormat(locale).format(value),
28
+ decimal(value, scale) {
29
+ if (value === null || value === undefined || value === '')
30
+ return '';
31
+ const match = /^(-?)(\d+)(?:\.(\d+))?$/.exec(value.trim());
32
+ if (match === null)
33
+ return value;
34
+ const [, sign, whole = '0', frac = ''] = match;
35
+ const fraction = scale === undefined ? frac.replace(/0+$/, '') : frac.padEnd(scale, '0').slice(0, scale);
36
+ const head = integer.format(BigInt(whole));
37
+ const tail = fraction === ''
38
+ ? ''
39
+ : `${separator}${[...fraction].map((d) => digits.format(Number(d))).join('')}`;
40
+ return `${sign === '-' ? '-' : ''}${head}${tail}`;
41
+ },
42
+ date: (value) => value === null || value === undefined || value === ''
43
+ ? ''
44
+ : date.format(new Date(`${value.slice(0, 10)}T00:00:00Z`)),
45
+ datetime: (value) => value === null || value === undefined || value === '' ? '' : datetime.format(new Date(value)),
46
+ };
47
+ }
48
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/lib/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The renderer registry (RFC 0004 §5 escape hatches, RFC 0007 §5): view renderers by type, field widgets by name
3
+ * (or field kind), and node components by name. Modules add entries; replacing an existing one must be asked for
4
+ * (`{ replace: true }`), so two modules cannot silently fight over a widget.
5
+ */
6
+ import type { ComponentNode, Condition, FieldNode, ViewType } from '@isahaq/kosh-views';
7
+ import type { ComponentType } from 'react';
8
+ import type { KoshApi, Row, ServedView, ViewField } from './api.js';
9
+ /** Props of a field widget (display and edit). */
10
+ export interface WidgetProps {
11
+ readonly id: string;
12
+ readonly node: FieldNode;
13
+ readonly field: ViewField;
14
+ readonly value: unknown;
15
+ readonly record: Readonly<Record<string, unknown>>;
16
+ readonly readonly: boolean;
17
+ /** Absent in display-only contexts (list cells, cards). */
18
+ readonly onChange?: (value: unknown) => void;
19
+ readonly invalid?: boolean;
20
+ }
21
+ /** Props of a registered node component (`{ kind: 'component', component: 'approvals.Panel' }`). */
22
+ export interface NodeComponentProps {
23
+ readonly node: ComponentNode;
24
+ readonly record: Row | null;
25
+ readonly model: string;
26
+ readonly served: ServedView;
27
+ readonly api: KoshApi;
28
+ /** The record's version (its ETag): changes after every save or transition, so components refetch with it. */
29
+ readonly version: string | null;
30
+ /** Reloads the record (after the component changed it on the server). */
31
+ readonly reload: () => void;
32
+ }
33
+ /** Props of a view renderer. */
34
+ export interface ViewProps {
35
+ readonly served: ServedView;
36
+ /** The compiled search (`@isahaq/kosh-search`). */
37
+ readonly where: Condition | undefined;
38
+ readonly groupBy: readonly string[];
39
+ readonly order: readonly string[];
40
+ readonly onOrder?: (order: readonly string[]) => void;
41
+ /** Opens a record (`'new'` for a new one) in the form. */
42
+ readonly onOpen: (id: number | 'new', defaults?: Record<string, unknown>) => void;
43
+ /** Drill-down (report views): shows the records of `domain` in the list. */
44
+ readonly onDrill?: (domain: Condition, label?: string) => void;
45
+ }
46
+ /** Props of the form renderer. */
47
+ export interface FormProps {
48
+ readonly served: ServedView;
49
+ readonly recordId: number | 'new';
50
+ readonly defaults?: Record<string, unknown>;
51
+ readonly onSaved: (id: number) => void;
52
+ readonly onBack: () => void;
53
+ }
54
+ export declare class RegistryError extends Error {
55
+ constructor(problem: string);
56
+ }
57
+ /** Renderers, widgets and components by name. */
58
+ export declare class Registry {
59
+ #private;
60
+ /** A view renderer for a view type (`list`, `form`, `kanban`) or a named custom view. */
61
+ registerView(type: ViewType | string, component: ComponentType<ViewProps> | ComponentType<FormProps>, options?: {
62
+ readonly replace?: boolean;
63
+ }): this;
64
+ /** A field widget, by name (`badge`) or field kind (`many2one`). */
65
+ registerWidget(name: string, component: ComponentType<WidgetProps>, options?: {
66
+ readonly replace?: boolean;
67
+ }): this;
68
+ /** A node component (`approvals.Panel`). */
69
+ registerComponent(name: string, component: ComponentType<NodeComponentProps>, options?: {
70
+ readonly replace?: boolean;
71
+ }): this;
72
+ view(name: string): ComponentType<ViewProps> | undefined;
73
+ form(name?: string): ComponentType<FormProps> | undefined;
74
+ /** The widget for a node: its `widget`, else the field kind, else plain text. */
75
+ widget(node: FieldNode, field: ViewField): ComponentType<WidgetProps>;
76
+ component(name: string): ComponentType<NodeComponentProps> | undefined;
77
+ /** A copy, for an app that changes entries without touching the defaults. */
78
+ clone(): Registry;
79
+ }
80
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ export class RegistryError extends Error {
2
+ constructor(problem) {
3
+ super(problem);
4
+ this.name = 'RegistryError';
5
+ }
6
+ }
7
+ /** Renderers, widgets and components by name. */
8
+ export class Registry {
9
+ #entries = {
10
+ view: new Map(),
11
+ widget: new Map(),
12
+ component: new Map(),
13
+ };
14
+ #add(kind, name, component, replace) {
15
+ if (this.#entries[kind].has(name) && !replace)
16
+ throw new RegistryError(`The ${kind} '${name}' is already registered. Pass { replace: true } to replace it.`);
17
+ this.#entries[kind].set(name, component);
18
+ return this;
19
+ }
20
+ /** A view renderer for a view type (`list`, `form`, `kanban`) or a named custom view. */
21
+ registerView(type, component, options = {}) {
22
+ return this.#add('view', type, component, options.replace === true);
23
+ }
24
+ /** A field widget, by name (`badge`) or field kind (`many2one`). */
25
+ registerWidget(name, component, options = {}) {
26
+ return this.#add('widget', name, component, options.replace === true);
27
+ }
28
+ /** A node component (`approvals.Panel`). */
29
+ registerComponent(name, component, options = {}) {
30
+ return this.#add('component', name, component, options.replace === true);
31
+ }
32
+ view(name) {
33
+ return this.#entries.view.get(name);
34
+ }
35
+ form(name = 'form') {
36
+ return this.#entries.view.get(name);
37
+ }
38
+ /** The widget for a node: its `widget`, else the field kind, else plain text. */
39
+ widget(node, field) {
40
+ const entries = this.#entries.widget;
41
+ return (entries.get(node.widget ?? '') ??
42
+ entries.get(field.kind) ??
43
+ entries.get('char'));
44
+ }
45
+ component(name) {
46
+ return this.#entries.component.get(name);
47
+ }
48
+ /** A copy, for an app that changes entries without touching the defaults. */
49
+ clone() {
50
+ const copy = new Registry();
51
+ for (const kind of ['view', 'widget', 'component'])
52
+ for (const [name, c] of this.#entries[kind])
53
+ copy.#entries[kind].set(name, c);
54
+ return copy;
55
+ }
56
+ }
57
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.tsx"],"names":[],"mappings":"AA0DA,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAID,iDAAiD;AACjD,MAAM,OAAO,QAAQ;IACV,QAAQ,GAAoD;QACnE,IAAI,EAAE,IAAI,GAAG,EAAE;QACf,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,SAAS,EAAE,IAAI,GAAG,EAAE;KACrB,CAAC;IAEF,IAAI,CAAC,IAAU,EAAE,IAAY,EAAE,SAA+B,EAAE,OAAgB;QAC9E,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO;YAC3C,MAAM,IAAI,aAAa,CACrB,OAAO,IAAI,KAAK,IAAI,gEAAgE,CACrF,CAAC;QACJ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yFAAyF;IACzF,YAAY,CACV,IAAuB,EACvB,SAA8D,EAC9D,OAAO,GAAmC,EAAE;QAE5C,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,SAAiC,EAAE,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;IAC9F,CAAC;IAED,oEAAoE;IACpE,cAAc,CACZ,IAAY,EACZ,SAAqC,EACrC,OAAO,GAAmC,EAAE;QAE5C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAiC,EAAE,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;IAChG,CAAC;IAED,4CAA4C;IAC5C,iBAAiB,CACf,IAAY,EACZ,SAA4C,EAC5C,OAAO,GAAmC,EAAE;QAE5C,OAAO,IAAI,CAAC,IAAI,CACd,WAAW,EACX,IAAI,EACJ,SAAiC,EACjC,OAAO,CAAC,OAAO,KAAK,IAAI,CACzB,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAY;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAyC,CAAC;IAC9E,CAAC;IAED,IAAI,CAAC,IAAI,GAAG,MAAM;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAyC,CAAC;IAC9E,CAAC;IAED,iFAAiF;IACjF,MAAM,CAAC,IAAe,EAAE,KAAgB;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAA+B,CAAC;IACvD,CAAC;IAED,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAkD,CAAC;IAC5F,CAAC;IAED,6EAA6E;IAC7E,KAAK;QACH,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,CAAU;YACzD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The search bar (RFC 0004 §5): text facets with suggestions per search field, filters, group-by, and favorites
3
+ * (saved searches, private or shared, stored as `kosh.saved_view` records). It edits a `@isahaq/kosh-search` state; the
4
+ * views compile it, so a search means the same in every view.
5
+ */
6
+ import { type SearchState } from '@isahaq/kosh-search';
7
+ import type { SearchSpec } from '@isahaq/kosh-views';
8
+ import { type ReactElement } from 'react';
9
+ export interface SearchBarProps {
10
+ readonly model: string;
11
+ readonly viewType: string;
12
+ readonly spec: SearchSpec;
13
+ readonly state: SearchState;
14
+ readonly onChange: (state: SearchState) => void;
15
+ /** Labels of search fields and group-by options (`company.name` → `Company`). */
16
+ readonly labels: Readonly<Record<string, string>>;
17
+ }
18
+ export declare function SearchBar({ model, viewType, spec, state, onChange, labels, }: SearchBarProps): ReactElement;
19
+ //# sourceMappingURL=SearchBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../src/search/SearchBar.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAIL,KAAK,WAAW,EAGjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAsB,KAAK,YAAY,EAAmB,MAAM,OAAO,CAAC;AAkB/E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,GACP,EAAE,cAAc,GAAG,YAAY,CA6Q/B"}
@@ -0,0 +1,84 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The search bar (RFC 0004 §5): text facets with suggestions per search field, filters, group-by, and favorites
4
+ * (saved searches, private or shared, stored as `kosh.saved_view` records). It edits a `@isahaq/kosh-search` state; the
5
+ * views compile it, so a search means the same in every view.
6
+ */
7
+ import { addFacet, isEmpty, removeFacet, suggestions, toggle, } from '@isahaq/kosh-search';
8
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
9
+ import { Filter, Layers, Search, Star, X } from 'lucide-react';
10
+ import { useId, useState } from 'react';
11
+ import { useTranslation } from 'react-i18next';
12
+ import { Button, Checkbox, Dialog, Input, Label, Menu, MenuCheckboxItem, MenuContent, MenuItem, MenuLabel, MenuSeparator, MenuTrigger, } from '../components/primitives.js';
13
+ import { useKosh } from '../context.js';
14
+ export function SearchBar({ model, viewType, spec, state, onChange, labels, }) {
15
+ const { t } = useTranslation();
16
+ const { api } = useKosh();
17
+ const queryClient = useQueryClient();
18
+ const [text, setText] = useState('');
19
+ const [active, setActive] = useState(0);
20
+ const [saving, setSaving] = useState(false);
21
+ const [name, setName] = useState('');
22
+ const [shared, setShared] = useState(false);
23
+ const listId = useId();
24
+ const options = suggestions(spec, text);
25
+ const label = (key) => labels[key] ?? key;
26
+ const favorites = useQuery({
27
+ queryKey: ['saved-views', model],
28
+ queryFn: () => api.list('kosh.saved_view', {
29
+ filter: { targetModel: model },
30
+ fields: ['name', 'state', 'shared', 'viewType'],
31
+ }),
32
+ });
33
+ const save = useMutation({
34
+ mutationFn: () => api.create('kosh.saved_view', { name, targetModel: model, viewType, state, shared }),
35
+ onSuccess: async () => {
36
+ setSaving(false);
37
+ setName('');
38
+ await queryClient.invalidateQueries({ queryKey: ['saved-views', model] });
39
+ },
40
+ });
41
+ const add = (index) => {
42
+ const option = options[index];
43
+ if (option === undefined)
44
+ return;
45
+ onChange(addFacet(state, option.field, option.value));
46
+ setText('');
47
+ setActive(0);
48
+ };
49
+ const onKeyDown = (e) => {
50
+ if (e.key === 'ArrowDown') {
51
+ e.preventDefault();
52
+ setActive((a) => Math.min(a + 1, options.length - 1));
53
+ }
54
+ else if (e.key === 'ArrowUp') {
55
+ e.preventDefault();
56
+ setActive((a) => Math.max(a - 1, 0));
57
+ }
58
+ else if (e.key === 'Enter') {
59
+ e.preventDefault();
60
+ add(active);
61
+ }
62
+ else if (e.key === 'Escape')
63
+ setText('');
64
+ else if (e.key === 'Backspace' && text === '' && (state.facets ?? []).length > 0) {
65
+ const last = (state.facets ?? [])[(state.facets ?? []).length - 1];
66
+ if (last !== undefined)
67
+ onChange(removeFacet(state, last.field));
68
+ }
69
+ };
70
+ const filterGroups = new Map();
71
+ for (const [key, filter] of Object.entries(spec.filters ?? {}))
72
+ filterGroups.set(filter.group ?? key, [
73
+ ...(filterGroups.get(filter.group ?? key) ?? []),
74
+ [key, filter],
75
+ ]);
76
+ return (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs("div", { className: "relative flex min-w-64 flex-1 flex-wrap items-center gap-1 rounded-md border border-input bg-surface px-2 py-1", children: [_jsx(Search, { className: "size-4 text-muted-foreground", "aria-hidden": true }), (state.facets ?? []).map((facet) => {
77
+ const description = `${label(facet.field)}: ${facet.values.join(` ${t('search.or')} `)}`;
78
+ return (_jsxs("span", { className: "inline-flex items-center gap-1 rounded bg-accent px-2 py-0.5 text-xs text-accent-foreground", children: [description, _jsx("button", { type: "button", "aria-label": t('search.remove', { facet: description }), onClick: () => onChange(removeFacet(state, facet.field)), children: _jsx(X, { className: "size-3", "aria-hidden": true }) })] }, facet.field));
79
+ }), (state.filters ?? []).map((key) => (_jsxs("span", { className: "inline-flex items-center gap-1 rounded bg-muted px-2 py-0.5 text-xs", children: [spec.filters?.[key]?.label ?? key, _jsx("button", { type: "button", "aria-label": t('search.remove', { facet: spec.filters?.[key]?.label ?? key }), onClick: () => onChange({ ...state, filters: toggle(state.filters, key) }), children: _jsx(X, { className: "size-3", "aria-hidden": true }) })] }, key))), (state.groupBy ?? []).map((key) => (_jsxs("span", { className: "inline-flex items-center gap-1 rounded bg-muted px-2 py-0.5 text-xs", children: [_jsx(Layers, { className: "size-3", "aria-hidden": true }), label(key), _jsx("button", { type: "button", "aria-label": t('search.remove', { facet: label(key) }), onClick: () => onChange({ ...state, groupBy: toggle(state.groupBy, key) }), children: _jsx(X, { className: "size-3", "aria-hidden": true }) })] }, key))), _jsx("input", { role: "combobox", "aria-label": t('search.placeholder'), "aria-expanded": options.length > 0, "aria-controls": listId, "aria-activedescendant": options.length > 0 ? `${listId}-${active}` : undefined, className: "h-7 min-w-24 flex-1 bg-transparent text-sm outline-none", placeholder: isEmpty(state) ? t('search.placeholder') : '', value: text, onChange: (e) => {
80
+ setText(e.target.value);
81
+ setActive(0);
82
+ }, onKeyDown: onKeyDown }), options.length > 0 ? (_jsx("div", { id: listId, role: "listbox", className: "absolute start-0 top-full z-40 mt-1 w-full rounded-md border bg-surface p-1 shadow-lg", children: options.map((o, i) => (_jsx("div", { id: `${listId}-${i}`, role: "option", "aria-selected": i === active, className: `cursor-default rounded-sm px-2 py-1.5 text-sm ${i === active ? 'bg-muted' : ''}`, onMouseDown: (e) => e.preventDefault(), onClick: () => add(i), children: t('search.searchFor', { field: label(o.field), value: o.value }) }, o.field))) })) : null, isEmpty(state) ? null : (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => onChange({}), children: t('search.clear') }))] }), filterGroups.size === 0 ? null : (_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs(Button, { size: "sm", children: [_jsx(Filter, { "aria-hidden": true }), t('search.filters')] }) }), _jsx(MenuContent, { children: [...filterGroups.values()].map((group, i) => (_jsxs("div", { children: [i > 0 ? _jsx(MenuSeparator, {}) : null, group.map(([key, filter]) => (_jsx(MenuCheckboxItem, { checked: (state.filters ?? []).includes(key), onSelect: (e) => e.preventDefault(), onCheckedChange: () => onChange({ ...state, filters: toggle(state.filters, key) }), children: filter.label }, key)))] }, group[0]?.[0] ?? i))) })] })), (spec.groupBy ?? []).length === 0 ? null : (_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs(Button, { size: "sm", children: [_jsx(Layers, { "aria-hidden": true }), t('search.groupBy')] }) }), _jsx(MenuContent, { children: (spec.groupBy ?? []).map((key) => (_jsx(MenuCheckboxItem, { checked: (state.groupBy ?? []).includes(key), onSelect: (e) => e.preventDefault(), onCheckedChange: () => onChange({ ...state, groupBy: toggle(state.groupBy, key) }), children: label(key) }, key))) })] })), _jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsx(Button, { size: "sm", "aria-label": t('search.favorites'), children: _jsx(Star, { "aria-hidden": true }) }) }), _jsxs(MenuContent, { children: [_jsx(MenuLabel, { children: t('search.favorites') }), (favorites.data?.items ?? []).map((saved) => (_jsx(MenuItem, { onSelect: () => onChange(saved['state'] ?? {}), children: String(saved['name']) }, saved.id))), _jsx(MenuSeparator, {}), _jsx(MenuItem, { onSelect: () => setSaving(true), children: t('search.saveCurrent') })] })] }), _jsx(Dialog, { open: saving, onOpenChange: setSaving, title: t('search.saveCurrent'), footer: _jsxs(_Fragment, { children: [_jsx(Button, { onClick: () => setSaving(false), children: t('views.discard') }), _jsx(Button, { variant: "primary", busy: save.isPending, disabled: name.trim() === '', onClick: () => save.mutate(), children: t('views.save') })] }), children: _jsxs("div", { className: "grid gap-3", children: [_jsxs("div", { className: "grid gap-1", children: [_jsx(Label, { htmlFor: `${listId}-name`, children: t('search.name') }), _jsx(Input, { id: `${listId}-name`, value: name, onChange: (e) => setName(e.target.value) })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: `${listId}-share`, checked: shared, onCheckedChange: (c) => setShared(c === true) }), _jsx(Label, { htmlFor: `${listId}-share`, children: t('search.share') })] })] }) })] }));
83
+ }
84
+ //# sourceMappingURL=SearchBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchBar.js","sourceRoot":"","sources":["../../src/search/SearchBar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { type ReactElement } from 'react';
2
+ import { type KoshApi } from '../api.js';
3
+ export declare function Login({ api, onSignedIn, }: {
4
+ readonly api: KoshApi;
5
+ readonly onSignedIn: () => void;
6
+ }): ReactElement;
7
+ //# sourceMappingURL=Login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Login.d.ts","sourceRoot":"","sources":["../../src/shell/Login.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAmB,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAGnD,wBAAgB,KAAK,CAAC,EACpB,GAAG,EACH,UAAU,GACX,EAAE;IACD,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;CACjC,GAAG,YAAY,CAgGf"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /** The sign-in page: login and password, then the second factor when the account has 2FA. */
3
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
4
+ import { useId, useState } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { ApiError } from '../api.js';
7
+ import { Alert, Button, Card, Input, Label } from '../components/primitives.js';
8
+ export function Login({ api, onSignedIn, }) {
9
+ const { t } = useTranslation();
10
+ const queryClient = useQueryClient();
11
+ const id = useId();
12
+ const [login, setLogin] = useState('');
13
+ const [password, setPassword] = useState('');
14
+ const [code, setCode] = useState('');
15
+ const [step, setStep] = useState('password');
16
+ const done = async () => {
17
+ await queryClient.invalidateQueries();
18
+ onSignedIn();
19
+ };
20
+ const signIn = useMutation({
21
+ mutationFn: () => api.login(login, password),
22
+ onSuccess: async ({ twoFactorRequired }) => {
23
+ if (twoFactorRequired)
24
+ setStep('code');
25
+ else
26
+ await done();
27
+ },
28
+ });
29
+ const verify = useMutation({ mutationFn: () => api.verifyTwoFactor(code), onSuccess: done });
30
+ const error = signIn.error ?? verify.error;
31
+ return (_jsx("main", { className: "grid min-h-screen place-items-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-sm p-6", children: [_jsx("h1", { className: "mb-1 text-xl font-semibold", children: t('app.name') }), _jsx("p", { className: "mb-5 text-sm text-muted-foreground", children: t('auth.signIn') }), error === null ? null : (_jsx("div", { className: "mb-4", children: _jsx(Alert, { children: error instanceof ApiError && error.kind === 'invalid-credentials'
32
+ ? t('auth.invalid')
33
+ : error.message }) })), step === 'password' ? (_jsxs("form", { className: "grid gap-4", onSubmit: (e) => {
34
+ e.preventDefault();
35
+ signIn.mutate();
36
+ }, children: [_jsxs("div", { className: "grid gap-1", children: [_jsx(Label, { htmlFor: `${id}-login`, children: t('auth.login') }), _jsx(Input, { id: `${id}-login`, autoComplete: "username", required: true, value: login, onChange: (e) => setLogin(e.target.value) })] }), _jsxs("div", { className: "grid gap-1", children: [_jsx(Label, { htmlFor: `${id}-password`, children: t('auth.password') }), _jsx(Input, { id: `${id}-password`, type: "password", autoComplete: "current-password", required: true, value: password, onChange: (e) => setPassword(e.target.value) })] }), _jsx(Button, { type: "submit", variant: "primary", busy: signIn.isPending, children: t('auth.signIn') })] })) : (_jsxs("form", { className: "grid gap-4", onSubmit: (e) => {
37
+ e.preventDefault();
38
+ verify.mutate();
39
+ }, children: [_jsxs("div", { className: "grid gap-1", children: [_jsx(Label, { htmlFor: `${id}-code`, children: t('auth.code') }), _jsx(Input, { id: `${id}-code`, autoComplete: "one-time-code", inputMode: "numeric", required: true, value: code, onChange: (e) => setCode(e.target.value) }), _jsx("p", { className: "text-xs text-muted-foreground", children: t('auth.codeHint') })] }), _jsx(Button, { type: "submit", variant: "primary", busy: verify.isPending, children: t('auth.verify') })] }))] }) }));
40
+ }
41
+ //# sourceMappingURL=Login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Login.js","sourceRoot":"","sources":["../../src/shell/Login.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { FormProps } from '../registry.js';
3
+ /** The default form renderer. */
4
+ export declare function FormView({ served, recordId, defaults, onSaved, onBack }: FormProps): ReactElement;
5
+ //# sourceMappingURL=FormView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormView.d.ts","sourceRoot":"","sources":["../../src/views/FormView.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,YAAY,EAAuC,MAAM,OAAO,CAAC;AAoB/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0LhD,iCAAiC;AACjC,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,GAAG,YAAY,CA2cjG"}