doom-design-system 0.6.0 → 0.7.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 (64) hide show
  1. package/dist/components/A2UI/catalog.js +98 -0
  2. package/dist/components/A2UI/mapping.js +5 -0
  3. package/dist/components/Checkbox/Checkbox.d.ts +1 -0
  4. package/dist/components/Checkbox/Checkbox.js +20 -4
  5. package/dist/components/FileUpload/FileUpload.js +2 -1
  6. package/dist/components/FileUpload/FileUpload.module.css +18 -14
  7. package/dist/components/Page/Page.module.css +9 -3
  8. package/dist/components/Popover/Popover.d.ts +1 -1
  9. package/dist/components/Popover/Popover.js +53 -23
  10. package/dist/components/Rating/Rating.d.ts +17 -0
  11. package/dist/components/Rating/Rating.js +126 -0
  12. package/dist/components/Rating/Rating.module.css +131 -0
  13. package/dist/components/Rating/index.d.ts +1 -0
  14. package/dist/components/Rating/index.js +1 -0
  15. package/dist/components/Table/Table.d.ts +2 -3
  16. package/dist/components/Table/Table.js +2 -20
  17. package/dist/components/ToggleGroup/ToggleGroup.d.ts +22 -0
  18. package/dist/components/ToggleGroup/ToggleGroup.js +157 -0
  19. package/dist/components/ToggleGroup/ToggleGroup.module.css +81 -0
  20. package/dist/components/ToggleGroup/index.d.ts +1 -0
  21. package/dist/components/ToggleGroup/index.js +1 -0
  22. package/dist/index.d.ts +2 -0
  23. package/dist/index.js +2 -0
  24. package/dist/lib/filter/ast/array-filter.d.ts +7 -0
  25. package/dist/lib/filter/ast/array-filter.js +16 -0
  26. package/dist/lib/filter/ast/evaluate.d.ts +6 -0
  27. package/dist/lib/filter/ast/evaluate.js +35 -0
  28. package/dist/lib/filter/ast/index.d.ts +5 -0
  29. package/dist/lib/filter/ast/index.js +4 -0
  30. package/dist/lib/filter/ast/operators.d.ts +7 -0
  31. package/dist/{components/Table/utils/filterAst.js → lib/filter/ast/operators.js} +0 -52
  32. package/dist/lib/filter/ast/simple.d.ts +7 -0
  33. package/dist/lib/filter/ast/simple.js +26 -0
  34. package/dist/lib/filter/ast/types.d.ts +24 -0
  35. package/dist/lib/filter/ast/types.js +1 -0
  36. package/dist/lib/filter/index.d.ts +7 -0
  37. package/dist/lib/filter/index.js +7 -0
  38. package/dist/lib/filter/ui/FilterBuilder.d.ts +25 -0
  39. package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterBuilder.js +3 -3
  40. package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterConditionRow.d.ts +1 -1
  41. package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterConditionRow.js +4 -4
  42. package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterGroup.d.ts +9 -9
  43. package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterGroup.js +7 -7
  44. package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterSheetNested.d.ts +3 -3
  45. package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterSheetNested.js +4 -4
  46. package/dist/lib/filter/ui/convert.d.ts +16 -0
  47. package/dist/lib/filter/ui/convert.js +60 -0
  48. package/dist/lib/filter/ui/index.d.ts +5 -0
  49. package/dist/lib/filter/ui/index.js +5 -0
  50. package/dist/lib/filter/ui/utils/tree-utils.d.ts +15 -0
  51. package/dist/styles/globals.css +3 -1
  52. package/dist/tsconfig.build.tsbuildinfo +1 -1
  53. package/dist/vitest.config.js +6 -1
  54. package/package.json +10 -3
  55. package/dist/components/Table/FilterBuilder/FilterBuilder.d.ts +0 -20
  56. package/dist/components/Table/FilterBuilder/utils/tree-utils.d.ts +0 -15
  57. package/dist/components/Table/utils/arrayFilter.d.ts +0 -7
  58. package/dist/components/Table/utils/arrayFilter.js +0 -21
  59. package/dist/components/Table/utils/filterAst.d.ts +0 -33
  60. /package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterBuilder.module.css +0 -0
  61. /package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterConditionRow.module.css +0 -0
  62. /package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterGroup.module.css +0 -0
  63. /package/dist/{components/Table/FilterBuilder → lib/filter/ui}/FilterSheet.module.css +0 -0
  64. /package/dist/{components/Table/FilterBuilder → lib/filter/ui}/utils/tree-utils.js +0 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Convenience helper that converts a flat `{ field: value }` map to a Filter
3
+ * tree using equality operators joined by AND. Returns null when no
4
+ * non-empty values are present.
5
+ */
6
+ export function simpleFiltersToFilter(selections) {
7
+ const conditions = Object.entries(selections)
8
+ .filter(([, value]) => value !== "" && value != null)
9
+ .map(([field, value], index) => ({
10
+ type: "condition",
11
+ field,
12
+ operator: "eq",
13
+ value,
14
+ logic: index > 0 ? "and" : undefined,
15
+ }));
16
+ if (conditions.length === 0) {
17
+ return null;
18
+ }
19
+ if (conditions.length === 1) {
20
+ return conditions[0];
21
+ }
22
+ return {
23
+ type: "group",
24
+ conditions,
25
+ };
26
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The canonical filter representation. Tree of conditions and nested groups.
3
+ * Treat as immutable — produce a new Filter rather than mutating in place.
4
+ *
5
+ * For the editable working version used by FilterBuilder UI, see FilterDraft.
6
+ */
7
+ export type Filter = FilterCondition | FilterGroup;
8
+ export interface FilterCondition {
9
+ readonly type: "condition";
10
+ readonly id?: string;
11
+ readonly field: string;
12
+ readonly operator: FilterOperatorKey;
13
+ readonly value: unknown;
14
+ /** Joins this condition with the previous sibling. Defaults to "and" when omitted. */
15
+ readonly logic?: "and" | "or";
16
+ }
17
+ export interface FilterGroup {
18
+ readonly type: "group";
19
+ readonly id?: string;
20
+ readonly conditions: ReadonlyArray<Filter>;
21
+ /** Joins this group with the previous sibling. Defaults to "and" when omitted. */
22
+ readonly logic?: "and" | "or";
23
+ }
24
+ export type FilterOperatorKey = "eq" | "neq" | "contains" | "startsWith" | "endsWith" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "isEmpty" | "isNotEmpty";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ export type { Filter, FilterCondition, FilterGroup, FilterOperatorKey, } from "./ast";
2
+ export { arrayIncludesFilter, evaluateFilter, type FilterOperatorDef, OPERATORS, simpleFiltersToFilter, } from "./ast";
3
+ export { draftToFilter, filterToDraft } from "./ui/convert";
4
+ export { countConditions, FilterBuilder, type FilterBuilderProps, type FilterField, flattenConditions, } from "./ui/FilterBuilder";
5
+ export { type FilterConditionData, FilterConditionRow, } from "./ui/FilterConditionRow";
6
+ export { ConditionRow, type FilterDraft, type FilterDraftCondition, type FilterDraftGroup, FilterGroup as FilterGroupView, } from "./ui/FilterGroup";
7
+ export { FilterSheetNested } from "./ui/FilterSheetNested";
@@ -0,0 +1,7 @@
1
+ export { arrayIncludesFilter, evaluateFilter, OPERATORS, simpleFiltersToFilter, } from "./ast/index.js";
2
+ // UI (presentational) — doom-styled FilterBuilder components
3
+ export { draftToFilter, filterToDraft } from "./ui/convert.js";
4
+ export { countConditions, FilterBuilder, flattenConditions, } from "./ui/FilterBuilder.js";
5
+ export { FilterConditionRow, } from "./ui/FilterConditionRow.js";
6
+ export { ConditionRow, FilterGroup as FilterGroupView, } from "./ui/FilterGroup.js";
7
+ export { FilterSheetNested } from "./ui/FilterSheetNested.js";
@@ -0,0 +1,25 @@
1
+ import { type FilterOperatorKey } from "../ast";
2
+ import type { FilterDraftCondition, FilterDraftGroup } from "./FilterGroup";
3
+ /**
4
+ * Describes a column the user can filter on. Provides display metadata
5
+ * (label, input type, select options) and optionally restricts which
6
+ * operators apply.
7
+ */
8
+ export interface FilterField {
9
+ key: string;
10
+ label: string;
11
+ type: "select" | "text" | "number";
12
+ options?: {
13
+ value: string;
14
+ label: string;
15
+ }[];
16
+ operators?: FilterOperatorKey[];
17
+ }
18
+ export interface FilterBuilderProps {
19
+ fields: FilterField[];
20
+ value: FilterDraftGroup | null;
21
+ onChange: (value: FilterDraftGroup) => void;
22
+ }
23
+ export declare function countConditions(group: FilterDraftGroup): number;
24
+ export declare function flattenConditions(group: FilterDraftGroup): FilterDraftCondition[];
25
+ export declare function FilterBuilder({ fields, value, onChange }: FilterBuilderProps): import("react/jsx-runtime").JSX.Element;
@@ -2,9 +2,9 @@
2
2
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
3
  import { ListFilter } from "lucide-react";
4
4
  import { useState } from "react";
5
- import { Button } from "../../Button/Button.js";
6
- import { Chip } from "../../Chip/Chip.js";
7
- import { OPERATORS } from "../utils/filterAst.js";
5
+ import { Button } from "../../../components/Button/Button.js";
6
+ import { Chip } from "../../../components/Chip/Chip.js";
7
+ import { OPERATORS } from "../ast/index.js";
8
8
  import styles from "./FilterBuilder.module.css";
9
9
  import { FilterSheetNested } from "./FilterSheetNested.js";
10
10
  export function countConditions(group) {
@@ -1,4 +1,4 @@
1
- import type { FilterOperatorKey } from "../utils/filterAst";
1
+ import type { FilterOperatorKey } from "../ast";
2
2
  import type { FilterField } from "./FilterBuilder";
3
3
  export interface FilterConditionData {
4
4
  id: string;
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Trash2 } from "lucide-react";
4
- import { Button } from "../../Button/Button.js";
5
- import { Input } from "../../Input/Input.js";
6
- import { Select } from "../../Select/Select.js";
7
- import { OPERATORS } from "../utils/filterAst.js";
4
+ import { Button } from "../../../components/Button/Button.js";
5
+ import { Input } from "../../../components/Input/Input.js";
6
+ import { Select } from "../../../components/Select/Select.js";
7
+ import { OPERATORS } from "../ast/index.js";
8
8
  import styles from "./FilterConditionRow.module.css";
9
9
  export function FilterConditionRow({ condition, fields, onChange, onRemove, }) {
10
10
  var _a;
@@ -1,6 +1,6 @@
1
- import type { FilterOperatorKey } from "../utils/filterAst";
1
+ import type { FilterOperatorKey } from "../ast";
2
2
  import type { FilterField } from "./FilterBuilder";
3
- export interface FilterConditionItem {
3
+ export interface FilterDraftCondition {
4
4
  type: "condition";
5
5
  id: string;
6
6
  field: string;
@@ -8,34 +8,34 @@ export interface FilterConditionItem {
8
8
  value: string;
9
9
  logic?: "and" | "or";
10
10
  }
11
- export interface FilterGroupItem {
11
+ export interface FilterDraftGroup {
12
12
  type: "group";
13
13
  id: string;
14
- children: FilterItem[];
14
+ children: FilterDraft[];
15
15
  collapsed?: boolean;
16
16
  logic?: "and" | "or";
17
17
  }
18
- export type FilterItem = FilterConditionItem | FilterGroupItem;
18
+ export type FilterDraft = FilterDraftCondition | FilterDraftGroup;
19
19
  export interface ConditionRowProps {
20
- item: FilterConditionItem;
20
+ item: FilterDraftCondition;
21
21
  fields: FilterField[];
22
22
  parentId: string;
23
23
  logic?: "and" | "or";
24
24
  showLogic?: boolean;
25
25
  isGlobalDragging: boolean;
26
- onUpdate: (updated: FilterConditionItem) => void;
26
+ onUpdate: (updated: FilterDraftCondition) => void;
27
27
  onRemove: () => void;
28
28
  onLogicChange?: (logic: "and" | "or") => void;
29
29
  }
30
30
  export declare function ConditionRow({ item, fields, parentId: _parentId, logic, showLogic, isGlobalDragging, onUpdate, onRemove, onLogicChange, }: ConditionRowProps): import("react/jsx-runtime").JSX.Element;
31
31
  interface FilterGroupProps {
32
- item: FilterGroupItem;
32
+ item: FilterDraftGroup;
33
33
  fields: FilterField[];
34
34
  parentId: string;
35
35
  depth?: number;
36
36
  showLogic?: boolean;
37
37
  isGlobalDragging?: boolean;
38
- onUpdate: (updated: FilterGroupItem) => void;
38
+ onUpdate: (updated: FilterDraftGroup) => void;
39
39
  onRemove?: () => void;
40
40
  onRemoveSourceById?: (id: string) => void;
41
41
  onLogicChange?: (logic: "and" | "or") => void;
@@ -4,13 +4,13 @@ import { useDraggable, useDroppable } from "@dnd-kit/core";
4
4
  import clsx from "clsx";
5
5
  import { ChevronDown, ChevronRight, GripVertical, Plus, Trash2, } from "lucide-react";
6
6
  import React, { useCallback, useEffect, useId, useRef, useState } from "react";
7
- import { Badge } from "../../Badge/Badge.js";
8
- import { Button } from "../../Button/Button.js";
9
- import { Card } from "../../Card/Card.js";
10
- import { Input } from "../../Input/Input.js";
11
- import { Select } from "../../Select/Select.js";
12
- import { Text } from "../../Text/Text.js";
13
- import { OPERATORS } from "../utils/filterAst.js";
7
+ import { Badge } from "../../../components/Badge/Badge.js";
8
+ import { Button } from "../../../components/Button/Button.js";
9
+ import { Card } from "../../../components/Card/Card.js";
10
+ import { Input } from "../../../components/Input/Input.js";
11
+ import { Select } from "../../../components/Select/Select.js";
12
+ import { Text } from "../../../components/Text/Text.js";
13
+ import { OPERATORS } from "../ast/index.js";
14
14
  import styles from "./FilterGroup.module.css";
15
15
  import { MAX_DEPTH } from "./utils/tree-utils.js";
16
16
  function countConditions(item) {
@@ -1,11 +1,11 @@
1
1
  import type { FilterField } from "./FilterBuilder";
2
- import type { FilterGroupItem } from "./FilterGroup";
2
+ import type { FilterDraftGroup } from "./FilterGroup";
3
3
  interface FilterSheetNestedProps {
4
4
  isOpen: boolean;
5
5
  onClose: () => void;
6
6
  fields: FilterField[];
7
- initialValue: FilterGroupItem | null;
8
- onApply: (group: FilterGroupItem) => void;
7
+ initialValue: FilterDraftGroup | null;
8
+ onApply: (group: FilterDraftGroup) => void;
9
9
  }
10
10
  export declare function FilterSheetNested({ isOpen, onClose, fields, initialValue, onApply, }: FilterSheetNestedProps): import("react/jsx-runtime").JSX.Element;
11
11
  export {};
@@ -2,10 +2,10 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, pointerWithin, TouchSensor, useSensor, useSensors, } from "@dnd-kit/core";
4
4
  import { useEffect, useId, useState } from "react";
5
- import { Button } from "../../Button/Button.js";
6
- import { Flex } from "../../Layout/Layout.js";
7
- import { Sheet } from "../../Sheet/Sheet.js";
8
- import { Text } from "../../Text/Text.js";
5
+ import { Button } from "../../../components/Button/Button.js";
6
+ import { Flex } from "../../../components/Layout/Layout.js";
7
+ import { Sheet } from "../../../components/Sheet/Sheet.js";
8
+ import { Text } from "../../../components/Text/Text.js";
9
9
  import { ConditionRow, FilterGroup } from "./FilterGroup.js";
10
10
  import styles from "./FilterSheet.module.css";
11
11
  import { getItemDepth, getMaxRelativeDepth, insertItem, MAX_DEPTH, removeItem, } from "./utils/tree-utils.js";
@@ -0,0 +1,16 @@
1
+ import type { Filter, FilterCondition, FilterGroup } from "../ast";
2
+ import type { FilterDraft, FilterDraftCondition, FilterDraftGroup } from "./FilterGroup";
3
+ /**
4
+ * Converts an editable FilterDraft (UI working state) into the canonical
5
+ * immutable Filter (evaluation-ready). Strips UI-only fields like
6
+ * `collapsed` and converts `children[]` to `conditions[]`.
7
+ */
8
+ export declare function draftToFilter(draft: FilterDraft): Filter;
9
+ /**
10
+ * Converts a canonical Filter into an editable FilterDraft. Generates IDs
11
+ * for any node missing one (the AST treats id as optional, the draft
12
+ * requires it for React keys and dnd identifiers).
13
+ */
14
+ export declare function filterToDraft(filter: Filter): FilterDraft;
15
+ export declare function conditionDraftToFilter(draft: FilterDraftCondition): FilterCondition;
16
+ export declare function groupDraftToFilter(draft: FilterDraftGroup): FilterGroup;
@@ -0,0 +1,60 @@
1
+ let idCounter = 0;
2
+ function nextId(prefix) {
3
+ idCounter += 1;
4
+ return `${prefix}-${Date.now().toString(36)}-${idCounter.toString(36)}`;
5
+ }
6
+ /**
7
+ * Converts an editable FilterDraft (UI working state) into the canonical
8
+ * immutable Filter (evaluation-ready). Strips UI-only fields like
9
+ * `collapsed` and converts `children[]` to `conditions[]`.
10
+ */
11
+ export function draftToFilter(draft) {
12
+ if (draft.type === "group") {
13
+ return {
14
+ type: "group",
15
+ id: draft.id,
16
+ logic: draft.logic,
17
+ conditions: draft.children.map(draftToFilter),
18
+ };
19
+ }
20
+ return {
21
+ type: "condition",
22
+ id: draft.id,
23
+ field: draft.field,
24
+ operator: draft.operator,
25
+ value: draft.value,
26
+ logic: draft.logic,
27
+ };
28
+ }
29
+ /**
30
+ * Converts a canonical Filter into an editable FilterDraft. Generates IDs
31
+ * for any node missing one (the AST treats id as optional, the draft
32
+ * requires it for React keys and dnd identifiers).
33
+ */
34
+ export function filterToDraft(filter) {
35
+ var _a, _b;
36
+ if (filter.type === "group") {
37
+ return {
38
+ type: "group",
39
+ id: (_a = filter.id) !== null && _a !== void 0 ? _a : nextId("group"),
40
+ logic: filter.logic,
41
+ children: filter.conditions.map(filterToDraft),
42
+ };
43
+ }
44
+ return {
45
+ type: "condition",
46
+ id: (_b = filter.id) !== null && _b !== void 0 ? _b : nextId("cond"),
47
+ field: filter.field,
48
+ operator: filter.operator,
49
+ value: filter.value == null ? "" : String(filter.value),
50
+ logic: filter.logic,
51
+ };
52
+ }
53
+ // Internal helpers re-exported so existing Table imports keep working.
54
+ // These accept FilterCondition/FilterGroup explicitly.
55
+ export function conditionDraftToFilter(draft) {
56
+ return draftToFilter(draft);
57
+ }
58
+ export function groupDraftToFilter(draft) {
59
+ return draftToFilter(draft);
60
+ }
@@ -0,0 +1,5 @@
1
+ export { draftToFilter, filterToDraft } from "./convert";
2
+ export { countConditions, FilterBuilder, type FilterBuilderProps, type FilterField, flattenConditions, } from "./FilterBuilder";
3
+ export { type FilterConditionData, FilterConditionRow, } from "./FilterConditionRow";
4
+ export { ConditionRow, type FilterDraft, type FilterDraftCondition, type FilterDraftGroup, FilterGroup, } from "./FilterGroup";
5
+ export { FilterSheetNested } from "./FilterSheetNested";
@@ -0,0 +1,5 @@
1
+ export { draftToFilter, filterToDraft } from "./convert.js";
2
+ export { countConditions, FilterBuilder, flattenConditions, } from "./FilterBuilder.js";
3
+ export { FilterConditionRow, } from "./FilterConditionRow.js";
4
+ export { ConditionRow, FilterGroup, } from "./FilterGroup.js";
5
+ export { FilterSheetNested } from "./FilterSheetNested.js";
@@ -0,0 +1,15 @@
1
+ import { FilterDraft, FilterDraftGroup } from "../FilterGroup";
2
+ export declare const MAX_DEPTH = 3;
3
+ export type DropPosition = "before" | "after" | "inside";
4
+ export declare function getItemDepth(root: FilterDraftGroup, id: string, currentDepth?: number): number;
5
+ export declare function getMaxRelativeDepth(item: FilterDraft): number;
6
+ export declare function findItemPath(root: FilterDraftGroup, targetId: string, path?: {
7
+ group: FilterDraftGroup;
8
+ index: number;
9
+ }[]): {
10
+ group: FilterDraftGroup;
11
+ index: number;
12
+ }[] | null;
13
+ export declare function removeItem(root: FilterDraftGroup, id: string): FilterDraftGroup;
14
+ export declare function findItem(root: FilterDraft, id: string): FilterDraft | null;
15
+ export declare function insertItem(root: FilterDraftGroup, item: FilterDraft, targetId: string, position: DropPosition): FilterDraftGroup;
@@ -67,6 +67,8 @@
67
67
  }
68
68
 
69
69
  :root {
70
+ --common-black: #000;
71
+ --common-white: #fff;
70
72
  --control-height: var(--size-8);
71
73
  --control-padding-x: var(--space-3);
72
74
  --control-padding-y: var(--space-1\.5);
@@ -95,7 +97,7 @@
95
97
  --chip-padding-x: var(--space-2);
96
98
  --chip-padding-y: var(--space-1);
97
99
  --chip-font-size: var(--text-xs);
98
- --width-sidebar: 280px;
100
+ --width-sidebar: 240px;
99
101
  --width-sidebar-collapsed: 64px;
100
102
  --width-panel: 400px;
101
103
  --width-panel-wide: 600px;