@k2b/ui 0.41.0 → 0.43.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 (74) hide show
  1. package/dist/base.css +22 -0
  2. package/dist/browser/actions/Dropdown.js +220 -110
  3. package/dist/browser/actions/Dropdown.js.map +1 -1
  4. package/dist/browser/actions/index.js.map +1 -1
  5. package/dist/browser/actions/menu-search.js +166 -0
  6. package/dist/browser/actions/menu-search.js.map +1 -0
  7. package/dist/browser/actions/menu-sheet.js +107 -13
  8. package/dist/browser/actions/menu-sheet.js.map +1 -1
  9. package/dist/browser/content/CalendarWeekView.js +13 -1
  10. package/dist/browser/content/CalendarWeekView.js.map +1 -1
  11. package/dist/browser/content/CountryMap.js +241 -0
  12. package/dist/browser/content/CountryMap.js.map +1 -0
  13. package/dist/browser/content/world-countries.js +9 -0
  14. package/dist/browser/content/world-countries.js.map +1 -0
  15. package/dist/browser/country-map.js +3 -0
  16. package/dist/browser/country-map.js.map +1 -0
  17. package/dist/browser/inputs/IconChoices.js +121 -0
  18. package/dist/browser/inputs/IconChoices.js.map +1 -0
  19. package/dist/browser/inputs/index.js +1 -0
  20. package/dist/browser/inputs/index.js.map +1 -1
  21. package/dist/browser/intl/messages.js +6 -0
  22. package/dist/browser/intl/messages.js.map +1 -1
  23. package/dist/browser/layout/AppWorkspace.js +118 -93
  24. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  25. package/dist/browser/text-editor/format.js +11 -7
  26. package/dist/browser/text-editor/format.js.map +1 -1
  27. package/dist/browser/text-editor/table.js +39 -11
  28. package/dist/browser/text-editor/table.js.map +1 -1
  29. package/dist/browser/text-editor.js +1 -1
  30. package/dist/browser/text-editor.js.map +1 -1
  31. package/dist/ssr/actions/Dropdown.js +118 -40
  32. package/dist/ssr/actions/Dropdown.js.map +1 -1
  33. package/dist/ssr/actions/index.js.map +1 -1
  34. package/dist/ssr/actions/menu-search.js +113 -0
  35. package/dist/ssr/actions/menu-search.js.map +1 -0
  36. package/dist/ssr/actions/menu-sheet.js +82 -13
  37. package/dist/ssr/actions/menu-sheet.js.map +1 -1
  38. package/dist/ssr/content/CalendarWeekView.js +13 -1
  39. package/dist/ssr/content/CalendarWeekView.js.map +1 -1
  40. package/dist/ssr/content/CountryMap.js +135 -0
  41. package/dist/ssr/content/CountryMap.js.map +1 -0
  42. package/dist/ssr/content/world-countries.js +9 -0
  43. package/dist/ssr/content/world-countries.js.map +1 -0
  44. package/dist/ssr/country-map.js +3 -0
  45. package/dist/ssr/country-map.js.map +1 -0
  46. package/dist/ssr/inputs/IconChoices.js +59 -0
  47. package/dist/ssr/inputs/IconChoices.js.map +1 -0
  48. package/dist/ssr/inputs/index.js +1 -0
  49. package/dist/ssr/inputs/index.js.map +1 -1
  50. package/dist/ssr/intl/messages.js +6 -0
  51. package/dist/ssr/intl/messages.js.map +1 -1
  52. package/dist/ssr/layout/AppWorkspace.js +40 -20
  53. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  54. package/dist/ssr/text-editor/format.js +11 -7
  55. package/dist/ssr/text-editor/format.js.map +1 -1
  56. package/dist/ssr/text-editor/table.js +39 -11
  57. package/dist/ssr/text-editor/table.js.map +1 -1
  58. package/dist/ssr/text-editor.js +1 -1
  59. package/dist/ssr/text-editor.js.map +1 -1
  60. package/dist/styles.css +1 -1
  61. package/dist/types/actions/Dropdown.d.ts +34 -3
  62. package/dist/types/actions/index.d.ts +1 -1
  63. package/dist/types/actions/menu-search.d.ts +27 -0
  64. package/dist/types/actions/menu-sheet.d.ts +5 -1
  65. package/dist/types/content/CountryMap.d.ts +21 -0
  66. package/dist/types/content/world-countries.d.ts +6 -0
  67. package/dist/types/country-map.d.ts +2 -0
  68. package/dist/types/inputs/IconChoices.d.ts +19 -0
  69. package/dist/types/inputs/index.d.ts +2 -0
  70. package/dist/types/intl/messages.d.ts +3 -0
  71. package/dist/types/layout/AppWorkspace.d.ts +6 -1
  72. package/dist/types/text-editor/table.d.ts +2 -0
  73. package/dist/types/text-editor.d.ts +1 -1
  74. package/package.json +9 -1
@@ -22,7 +22,8 @@ export type DropdownActionBase = {
22
22
  description?: string;
23
23
  /** Quiet trailing information, such as a count. */
24
24
  trailing?: JSX.Element;
25
- variant?: "danger";
25
+ /** `danger` for destructive entries; `accent` for the entry most people want, such as creating a blank item. */
26
+ variant?: "danger" | "accent";
26
27
  };
27
28
  export type DropdownAction = (DropdownActionBase & {
28
29
  action: () => void;
@@ -83,9 +84,23 @@ export type DropdownSection = {
83
84
  items: readonly (DropdownAction | DropdownChoice)[];
84
85
  };
85
86
  export type DropdownItem = DropdownAction | DropdownChoice | DropdownSection;
87
+ /** A search field above the entries, for a menu long enough that finding an entry takes reading. */
88
+ export type DropdownSearch = {
89
+ /** Names the field and is its placeholder unless `placeholder` is set, such as "Find template". */
90
+ label: string;
91
+ placeholder?: string;
92
+ /**
93
+ * The entries for a query that is not blank. Defaults to the actions and choices whose label or description contains
94
+ * the query, kept in their sections.
95
+ */
96
+ filter?: (query: string) => readonly DropdownItem[];
97
+ /** What a screen reader hears after the query changes; defaults to the number of matching entries. */
98
+ status?: (query: string, matches: number) => string;
99
+ };
86
100
  export type DropdownProps = {
87
101
  items: readonly DropdownItem[];
88
- children: JSX.Element;
102
+ /** The `Dropdown.Trigger`; leave it out for a menu opened through `attach` or `openAt`. */
103
+ children?: JSX.Element;
89
104
  position?: DropdownPosition | (() => DropdownPosition);
90
105
  /** Larger menu rows and typography for touch. Defaults to `default`. */
91
106
  variant?: "default" | "touch";
@@ -123,6 +138,21 @@ export type DropdownProps = {
123
138
  openAt?: (open: (anchor: DropdownAnchor, returnFocus?: DropdownReturnFocus) => void) => void;
124
139
  /** Receives `close`, which closes the menu or sheet and returns focus. */
125
140
  closeWith?: (close: () => void) => void;
141
+ /**
142
+ * Puts a search field above the entries. Focus starts in the field; Up and Down move through the matching entries,
143
+ * Enter chooses one, and the first stays marked while the query changes.
144
+ */
145
+ search?: DropdownSearch;
146
+ /**
147
+ * Adopts an element rendered elsewhere as the trigger, such as a server-rendered link: a plain click, Enter, Space,
148
+ * Up, or Down opens the menu, while a modified or middle click keeps the link. The element gets `aria-expanded` and
149
+ * `aria-controls`; render `aria-haspopup` with it, so the server HTML already says it opens a menu. Read once on mount.
150
+ */
151
+ attach?: () => HTMLElement | null | undefined;
152
+ /** `tile` sets every entry's icon on a quiet square, for menus whose icons tell entries apart, such as templates. */
153
+ icons?: "plain" | "tile";
154
+ /** One quiet sentence below the entries that explains them all, such as what choosing one keeps; it describes the menu. */
155
+ note?: string;
126
156
  };
127
157
  export type DropdownTriggerProps = Omit<ButtonProps, "aria-controls" | "aria-expanded" | "aria-haspopup" | "children" | "disabled" | "onClick" | "onKeyDown"> & {
128
158
  children: JSX.Element;
@@ -148,7 +178,7 @@ export type DropdownItemProps = {
148
178
  trailing?: JSX.Element;
149
179
  disabled?: boolean;
150
180
  danger?: boolean;
151
- variant?: "danger";
181
+ variant?: "danger" | "accent";
152
182
  href?: string;
153
183
  external?: boolean;
154
184
  /** Runs when the item is chosen. With `href`, a plain click runs it instead of following the link. */
@@ -166,6 +196,7 @@ export declare function DropdownItem(props: DropdownItemProps): JSX.Element;
166
196
  export declare function DropdownItems(props: {
167
197
  items: readonly DropdownItem[];
168
198
  close: (restoreFocus?: boolean) => void;
199
+ role?: "menuitem" | "option";
169
200
  }): JSX.Element;
170
201
  type DropdownComponent = ((props: DropdownProps) => JSX.Element) & {
171
202
  Root: (props: DropdownProps) => JSX.Element;
@@ -8,7 +8,7 @@ export type { DisclosureProps } from "./Disclosure";
8
8
  export { Disclosure } from "./Disclosure";
9
9
  export type { DragPayload, DragSourceProps, DropTargetProps } from "./DragAndDrop";
10
10
  export { activeDrag, DragSource, DropTarget, useKeyboardDrag } from "./DragAndDrop";
11
- export type { DropdownAction, DropdownActionBase, DropdownAnchor, DropdownChoice, DropdownItemProps, DropdownPosition, DropdownProps, DropdownReturnFocus, DropdownSection, DropdownTriggerProps, } from "./Dropdown";
11
+ export type { DropdownAction, DropdownActionBase, DropdownAnchor, DropdownChoice, DropdownItemProps, DropdownPosition, DropdownProps, DropdownReturnFocus, DropdownSearch, DropdownSection, DropdownTriggerProps, } from "./Dropdown";
12
12
  export { Dropdown, DropdownItem, dropdownPosition } from "./Dropdown";
13
13
  export type { FilterChipOption, FilterChipProps, FilterChipSection, FilterToggleProps } from "./FilterChip";
14
14
  export { FilterChip, FilterToggle } from "./FilterChip";
@@ -0,0 +1,27 @@
1
+ import { type Accessor, type JSX } from "solid-js";
2
+ import type { DropdownItem, DropdownSearch } from "./Dropdown";
3
+ /** The actions and choices whose label or description contains the query, kept in their sections. */
4
+ export declare const filterDropdownItems: (items: readonly DropdownItem[], query: string, locale?: string) => DropdownItem[];
5
+ export type MenuSearchApi = {
6
+ /** Moves the focus into the field and marks the first or last entry. */
7
+ focus: (mark: "first" | "last") => void;
8
+ };
9
+ /**
10
+ * A search field over a list box of the menu's entries: the combobox pattern. The field keeps the focus, the marked
11
+ * entry is its active descendant, and a polite status says how many entries match.
12
+ */
13
+ export declare function MenuSearch(props: {
14
+ Items: (props: {
15
+ items: readonly DropdownItem[];
16
+ close: (restoreFocus?: boolean) => void;
17
+ role?: "menuitem" | "option";
18
+ }) => JSX.Element;
19
+ items: readonly DropdownItem[];
20
+ search: DropdownSearch;
21
+ /** Names the list box. */
22
+ label: string;
23
+ query: Accessor<string>;
24
+ setQuery: (query: string) => void;
25
+ close: (restoreFocus?: boolean) => void;
26
+ api?: (api: MenuSearchApi) => void;
27
+ }): JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { type JSX } from "solid-js";
2
- import type { DropdownItem } from "./Dropdown";
2
+ import type { DropdownItem, DropdownSearch } from "./Dropdown";
3
3
  /** Phones, where a menu opens as a bottom sheet instead of beside its trigger. */
4
4
  export declare const PHONE_SHEET_QUERY = "(max-width: 47.999rem)";
5
5
  export declare const prefersMenuSheet: () => boolean;
@@ -16,6 +16,10 @@ export type MenuSheetOptions = {
16
16
  locale: string;
17
17
  /** Shown above the menu, for example a row of quick reactions. `close` closes the sheet. */
18
18
  top?: (close: () => void) => JSX.Element;
19
+ search?: DropdownSearch;
20
+ icons?: "plain" | "tile";
21
+ /** A quiet sentence below the entries. */
22
+ note?: string;
19
23
  signal?: AbortSignal;
20
24
  };
21
25
  /** Opens menu items as a bottom sheet; resolves after the sheet closed and the chosen action ran. */
@@ -0,0 +1,21 @@
1
+ import { type JSX } from "solid-js";
2
+ export type CountryMapDatum = {
3
+ /** ISO 3166-1 alpha-2 code. Other values appear neither on the map nor in the list. */
4
+ code: string;
5
+ value: number;
6
+ };
7
+ export type CountryMapProps = {
8
+ data: readonly CountryMapDatum[];
9
+ /** Accessible name of the map, such as the panel title. */
10
+ label: string;
11
+ format?: (value: number) => string;
12
+ /** How many countries the ranked list names. */
13
+ limit?: number;
14
+ class?: string;
15
+ };
16
+ /**
17
+ * A world map that shades countries by one value, with a ranked list that names the same numbers.
18
+ * The geometry ships with the component, so the map makes no network request.
19
+ * @example <CountryMap label="Visitors" data={[{ code: "DE", value: 1200 }, { code: "FR", value: 300 }]} />
20
+ */
21
+ export declare function CountryMap(props: CountryMapProps): JSX.Element;
@@ -0,0 +1,6 @@
1
+ export declare const WORLD_MAP_VIEW_WIDTH = 1000;
2
+ export declare const WORLD_MAP_VIEW_HEIGHT = 450;
3
+ /** ISO 3166-1 alpha-2 code and SVG path. */
4
+ export declare const WORLD_COUNTRY_SHAPES: readonly (readonly [string, string])[];
5
+ /** Countries too small for a shape: ISO 3166-1 alpha-2 code, x and y. */
6
+ export declare const WORLD_COUNTRY_DOTS: readonly (readonly [string, number, number])[];
@@ -0,0 +1,2 @@
1
+ /** A separate entry because the country shapes weigh about 90 KB; load it only where a map appears. */
2
+ export { CountryMap, type CountryMapDatum, type CountryMapProps } from "./content/CountryMap";
@@ -0,0 +1,19 @@
1
+ import { type JSX } from "solid-js";
2
+ import type { ValueFieldProps } from "./field-contract";
3
+ export type IconChoiceOption<T extends string = string> = {
4
+ value: T;
5
+ /** What the icon shows; screen readers and the tooltip use it, so the picture is never the only signal. */
6
+ label: string;
7
+ /** An icon class, such as `ti ti-report`. */
8
+ icon: string;
9
+ };
10
+ export type IconChoicesProps<T extends string = string> = Omit<ValueFieldProps<T | null>, "onValueChange" | "onValueCommit"> & {
11
+ options: readonly IconChoiceOption<T>[];
12
+ onValueChange?: (value: T) => void;
13
+ onValueCommit?: (value: T) => void;
14
+ };
15
+ /**
16
+ * A labeled single choice from a few named icons, shown as a row of icon buttons. Use `IconInput` when any icon of the
17
+ * catalogue is allowed.
18
+ */
19
+ export declare function IconChoices<T extends string = string>(props: IconChoicesProps<T>): JSX.Element;
@@ -39,6 +39,8 @@ export { FileDropTarget, fileDropTarget } from "./FileDropTarget";
39
39
  export type { FileDropzoneProps, ImageCropperProps, ImageInputProps } from "./FileInputs";
40
40
  export { FileDropzone, ImageCropper, ImageInput } from "./FileInputs";
41
41
  export type { DateContext, FieldProps, MaybeAccessor, ValueFieldProps } from "./field-contract";
42
+ export type { IconChoiceOption, IconChoicesProps } from "./IconChoices";
43
+ export { IconChoices } from "./IconChoices";
42
44
  export { DEFAULT_ICON_GROUPS, DEFAULT_ICON_OPTIONS } from "./icon-options";
43
45
  export type { ImageCropAspect, ImageCropOutput, ImageCropRect, ImageCropRotation, ImageCropSize, ImageCropSource, ImageCropState, } from "./image-crop";
44
46
  export { clampImageCropRect, createCroppedImageCanvas, createCroppedImageDataUrl, getInitialImageCropRect, imageCropRectToPixels, normalizeImageCropRotation, resizeImageCropAroundCenter, rotateImageCropRight, } from "./image-crop";
@@ -42,6 +42,9 @@ declare const uiMessages: import("@k2b/stdlib").Catalog<{
42
42
  search: string;
43
43
  searchLabel: string;
44
44
  searchResults: string;
45
+ searchMatches: ({ count }: {
46
+ count: number;
47
+ }) => string;
45
48
  save: string;
46
49
  select: string;
47
50
  time: string;
@@ -21,12 +21,17 @@ export type AppWorkspaceHeadProps = {
21
21
  count?: JSX.Element;
22
22
  /** Secondary actions at the end of the row. Never a filled button. */
23
23
  actions?: JSX.Element;
24
- /** The one filled primary action. Below 48rem it becomes a round icon button beside the host's bottom bar. */
24
+ /**
25
+ * The one filled primary action. Below 48rem it becomes a round icon button beside the host's bottom bar. `popup`
26
+ * says it opens a menu, such as one a `Dropdown` with `attach` shows: server HTML then carries `aria-haspopup`, and a
27
+ * chevron follows the label.
28
+ */
25
29
  primary?: {
26
30
  label: string;
27
31
  icon: string;
28
32
  href?: string;
29
33
  onClick?: (event: MouseEvent) => void;
34
+ popup?: "menu" | "dialog";
30
35
  };
31
36
  };
32
37
  export type AppWorkspaceProps = {
@@ -61,6 +61,8 @@ export type TableHost = {
61
61
  export type MenuAction = "completeColumns" | "rowAbove" | "rowBelow" | "colLeft" | "colRight" | "deleteRow" | "deleteCol" | "moveRowUp" | "moveRowDown" | "moveColLeft" | "moveColRight" | "toggleHeader" | "deleteTable" | "alignLeft" | "alignCenter" | "alignRight";
62
62
  export declare const tableHost: Facet<TableHost, TableHost | null>;
63
63
  export declare const tablesIn: (state: EditorState) => T.Table[];
64
+ /** Render the same Markdown tokens as prose, keeping code and escaped markers literal. */
65
+ export declare const renderInline: (raw: string) => string;
64
66
  /** A local source draft for one table. Invalid drafts never replace shared text.
65
67
  * Collaborative structure changes require the host's confirmed anchored action. */
66
68
  export declare const editTableSource: (view: EditorView, wrap: HTMLElement) => void;
@@ -2,4 +2,4 @@ export { codeMirrorDictationTarget, dictationExtension } from "./text-editor/dic
2
2
  export { createTextEditor, type TextEditorController, type TextEditorMode, type TextEditorOptions } from "./text-editor/engine";
3
3
  export { commands as textEditorCommands, formatLabels as textEditorFormatLabels, type InlineFormat } from "./text-editor/format";
4
4
  export { TableSizePicker, type TableSizePickerProps, TextEditor, type TextEditorControls, type TextEditorProps, } from "./text-editor/TextEditor";
5
- export { editTableSource, type MenuAction, runMenuAction, runTableAction, type TableFocusTarget, type TableHost, type TableTarget, tableGrid, tableHost, } from "./text-editor/table";
5
+ export { editTableSource, type MenuAction, renderInline, runMenuAction, runTableAction, type TableFocusTarget, type TableHost, type TableTarget, tableGrid, tableHost, } from "./text-editor/table";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k2b/ui",
3
- "version": "0.41.0",
3
+ "version": "0.43.0",
4
4
  "description": "Production-ready components for SolidJS applications.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -36,6 +36,12 @@
36
36
  "browser": "./dist/browser/charts.js",
37
37
  "default": "./dist/ssr/charts.js"
38
38
  },
39
+ "./country-map": {
40
+ "types": "./dist/types/country-map.d.ts",
41
+ "browser": "./dist/browser/country-map.js",
42
+ "import": "./dist/ssr/country-map.js",
43
+ "default": "./dist/ssr/country-map.js"
44
+ },
39
45
  "./package.json": "./package.json",
40
46
  "./map-glyphs/*": "./map-glyphs/*",
41
47
  "./text-editor": {
@@ -61,6 +67,8 @@
61
67
  "fixture:build": "bun run build && NODE_ENV=production bun run fixture/scripts/build.ts",
62
68
  "fixture:typecheck": "tsc -p fixture/tsconfig.json --noEmit --pretty false",
63
69
  "test": "bun run build && bun test --path-ignore-patterns '**/*.behavior.test.*' src scripts test/browser.browser.test.ts && bun run scripts/check-packed-consumer.ts",
70
+ "test:part:layout-content": "bun run build && bun test --path-ignore-patterns '**/*.behavior.test.*' src/layout src/content",
71
+ "test:part:rest": "bun run build && bun test --path-ignore-patterns '**/*.behavior.test.*' --path-ignore-patterns 'src/layout/**' --path-ignore-patterns 'src/content/**' src scripts test/browser.browser.test.ts && bun run scripts/check-packed-consumer.ts",
64
72
  "typecheck": "tsc --checkers 2 -p tsconfig.json --noEmit --pretty false && bun run check:declarations && bun run typecheck:dom",
65
73
  "typecheck:dom": "tsc -p test/tsconfig.json --noEmit --pretty false",
66
74
  "prepack": "bun run build"