@k2b/ui 0.45.0 → 0.46.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 (96) hide show
  1. package/dist/browser/actions/Dropdown.js +8 -1
  2. package/dist/browser/actions/Dropdown.js.map +1 -1
  3. package/dist/browser/actions/FilterChip.js +11 -5
  4. package/dist/browser/actions/FilterChip.js.map +1 -1
  5. package/dist/browser/actions/ViewTabs.js +225 -93
  6. package/dist/browser/actions/ViewTabs.js.map +1 -1
  7. package/dist/browser/content/FileGrid.js +125 -99
  8. package/dist/browser/content/FileGrid.js.map +1 -1
  9. package/dist/browser/inputs/choice.js +36 -9
  10. package/dist/browser/inputs/choice.js.map +1 -1
  11. package/dist/browser/layout/AppWorkspace.js +30 -26
  12. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  13. package/dist/browser/layout/DetailPanel.js +130 -108
  14. package/dist/browser/layout/DetailPanel.js.map +1 -1
  15. package/dist/browser/layout/DetailSections.js +1019 -0
  16. package/dist/browser/layout/DetailSections.js.map +1 -0
  17. package/dist/browser/layout/DetailsToggle.js +32 -0
  18. package/dist/browser/layout/DetailsToggle.js.map +1 -0
  19. package/dist/browser/layout/Discussion.js +3 -0
  20. package/dist/browser/layout/Discussion.js.map +1 -1
  21. package/dist/browser/layout/MobileShell.js +116 -94
  22. package/dist/browser/layout/MobileShell.js.map +1 -1
  23. package/dist/browser/layout/PageTitle.js +33 -10
  24. package/dist/browser/layout/PageTitle.js.map +1 -1
  25. package/dist/browser/layout/app-workspace-controller.js +12 -0
  26. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  27. package/dist/browser/layout/detail-sections-messages.js +123 -0
  28. package/dist/browser/layout/detail-sections-messages.js.map +1 -0
  29. package/dist/browser/layout/index.js +2 -0
  30. package/dist/browser/layout/index.js.map +1 -1
  31. package/dist/browser/surfaces/Avatar.js +3 -1
  32. package/dist/browser/surfaces/Avatar.js.map +1 -1
  33. package/dist/browser/surfaces/AvatarStack.js +95 -61
  34. package/dist/browser/surfaces/AvatarStack.js.map +1 -1
  35. package/dist/browser/surfaces/ChangeList.js +77 -0
  36. package/dist/browser/surfaces/ChangeList.js.map +1 -0
  37. package/dist/browser/surfaces/index.js +2 -1
  38. package/dist/browser/surfaces/index.js.map +1 -1
  39. package/dist/browser/text-editor/TextEditor.js +19 -8
  40. package/dist/browser/text-editor/TextEditor.js.map +1 -1
  41. package/dist/ssr/actions/Dropdown.js +6 -0
  42. package/dist/ssr/actions/Dropdown.js.map +1 -1
  43. package/dist/ssr/actions/FilterChip.js +1 -1
  44. package/dist/ssr/actions/FilterChip.js.map +1 -1
  45. package/dist/ssr/actions/ViewTabs.js +144 -37
  46. package/dist/ssr/actions/ViewTabs.js.map +1 -1
  47. package/dist/ssr/content/FileGrid.js +36 -22
  48. package/dist/ssr/content/FileGrid.js.map +1 -1
  49. package/dist/ssr/inputs/choice.js +36 -9
  50. package/dist/ssr/inputs/choice.js.map +1 -1
  51. package/dist/ssr/layout/AppWorkspace.js +27 -27
  52. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  53. package/dist/ssr/layout/DetailPanel.js +17 -0
  54. package/dist/ssr/layout/DetailPanel.js.map +1 -1
  55. package/dist/ssr/layout/DetailSections.js +762 -0
  56. package/dist/ssr/layout/DetailSections.js.map +1 -0
  57. package/dist/ssr/layout/DetailsToggle.js +29 -0
  58. package/dist/ssr/layout/DetailsToggle.js.map +1 -0
  59. package/dist/ssr/layout/Discussion.js +3 -0
  60. package/dist/ssr/layout/Discussion.js.map +1 -1
  61. package/dist/ssr/layout/MobileShell.js +45 -28
  62. package/dist/ssr/layout/MobileShell.js.map +1 -1
  63. package/dist/ssr/layout/PageTitle.js +29 -6
  64. package/dist/ssr/layout/PageTitle.js.map +1 -1
  65. package/dist/ssr/layout/app-workspace-controller.js +12 -0
  66. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  67. package/dist/ssr/layout/detail-sections-messages.js +123 -0
  68. package/dist/ssr/layout/detail-sections-messages.js.map +1 -0
  69. package/dist/ssr/layout/index.js +2 -0
  70. package/dist/ssr/layout/index.js.map +1 -1
  71. package/dist/ssr/surfaces/Avatar.js +3 -1
  72. package/dist/ssr/surfaces/Avatar.js.map +1 -1
  73. package/dist/ssr/surfaces/AvatarStack.js +61 -32
  74. package/dist/ssr/surfaces/AvatarStack.js.map +1 -1
  75. package/dist/ssr/surfaces/ChangeList.js +37 -0
  76. package/dist/ssr/surfaces/ChangeList.js.map +1 -0
  77. package/dist/ssr/surfaces/index.js +2 -1
  78. package/dist/ssr/surfaces/index.js.map +1 -1
  79. package/dist/ssr/text-editor/TextEditor.js +19 -8
  80. package/dist/ssr/text-editor/TextEditor.js.map +1 -1
  81. package/dist/styles.css +1 -1
  82. package/dist/types/actions/FilterChip.d.ts +4 -0
  83. package/dist/types/actions/ViewTabs.d.ts +11 -1
  84. package/dist/types/content/FileGrid.d.ts +6 -0
  85. package/dist/types/inputs/choice.d.ts +9 -3
  86. package/dist/types/layout/DetailPanel.d.ts +9 -0
  87. package/dist/types/layout/DetailSections.d.ts +156 -0
  88. package/dist/types/layout/DetailsToggle.d.ts +13 -0
  89. package/dist/types/layout/PageTitle.d.ts +7 -0
  90. package/dist/types/layout/detail-sections-messages.d.ts +59 -0
  91. package/dist/types/layout/index.d.ts +4 -1
  92. package/dist/types/surfaces/Avatar.d.ts +3 -0
  93. package/dist/types/surfaces/AvatarStack.d.ts +20 -1
  94. package/dist/types/surfaces/ChangeList.d.ts +20 -0
  95. package/dist/types/surfaces/index.d.ts +5 -3
  96. package/package.json +3 -3
@@ -58,6 +58,10 @@ export type FilterToggleProps = {
58
58
  /** Link to the URL with the filter switched. The link keeps working without JavaScript. */
59
59
  href?: string;
60
60
  onClick?: (event: MouseEvent) => void;
61
+ /** The button opens a dialog with more filters, such as a filter builder; it stays pressed while they apply. */
62
+ opensDialog?: boolean;
63
+ /** The button is loading what it opens; it stays enabled so it keeps focus for the dialog to return it. */
64
+ busy?: boolean;
61
65
  title?: string;
62
66
  disabled?: boolean;
63
67
  class?: string;
@@ -5,6 +5,10 @@ export type ViewTab = {
5
5
  href: string;
6
6
  icon?: string;
7
7
  count?: number | string;
8
+ /** A short quiet label after the count, such as "New" for a view people have not opened yet. */
9
+ badge?: string;
10
+ /** Stays in the strip after More at every width, for a view of another kind than the ones that overflow. */
11
+ pinned?: boolean;
8
12
  };
9
13
  export type ViewTabsProps = {
10
14
  /** Accessible name of the navigation landmark, e.g. "Views". */
@@ -12,14 +16,20 @@ export type ViewTabsProps = {
12
16
  items: readonly ViewTab[];
13
17
  /** Id of the open view; the server reads it from `?view=`. Unknown ids select nothing. */
14
18
  current: string | undefined;
15
- /** Tabs shown before More (default 5). */
19
+ /** At most this many views before More (default 5). */
16
20
  max?: number;
21
+ /**
22
+ * The strip shows only the views that fit its room and counts the rest in More, instead of scrolling them. The open
23
+ * view and pinned views stay. Pair it with a larger `max` so a wide head shows more views.
24
+ */
25
+ fit?: boolean;
17
26
  class?: string;
18
27
  };
19
28
  /** Two deterministic strip levels; only opening the menu reads CSS visibility. */
20
29
  export declare function viewTabsLayout(items: readonly ViewTab[], current: string | undefined, max?: number): {
21
30
  wide: number[];
22
31
  compact: number[];
32
+ pinned: number[];
23
33
  wideHidden: number;
24
34
  compactHidden: number;
25
35
  };
@@ -34,6 +34,11 @@ type FileGridBaseProps<T> = {
34
34
  export type FileGridSelectableProps<T> = FileGridBaseProps<T> & {
35
35
  selection: CollectionSelection;
36
36
  onRowClick?: (row: T) => void;
37
+ /**
38
+ * Shows a check box before each item that `checks` returns `true` for, or a circle when only one item may be
39
+ * selected. The check only mirrors the selection; items without one keep its slot, so names stay in line.
40
+ */
41
+ checks?: (row: T) => boolean;
37
42
  limit?: never;
38
43
  expanded?: never;
39
44
  onExpandedChange?: never;
@@ -45,6 +50,7 @@ export type FileGridSelectableProps<T> = FileGridBaseProps<T> & {
45
50
  export type FileGridOpenProps<T> = FileGridBaseProps<T> & {
46
51
  selection?: never;
47
52
  onRowClick?: never;
53
+ checks?: never;
48
54
  /** Shows the first `limit` items, then "Show all N", which opens the full list in place. Without it, the list is always full. */
49
55
  limit?: number;
50
56
  /** Controls whether the full list is open. Without it, the list keeps its own state. */
@@ -45,14 +45,20 @@ export declare function createChoiceLoader<T extends string>(loader: () => Choic
45
45
  };
46
46
  export type ChoicePopoverPlacement = {
47
47
  /**
48
- * `trigger` (default) gives the popover the trigger's width; `own` keeps the
49
- * width its stylesheet sets, such as a RichSelect with a preview.
48
+ * `trigger` (default) makes the popover at least as wide as the trigger and
49
+ * as wide as its longest name, so names stay on one line; `own` keeps
50
+ * the width its stylesheet sets, such as a RichSelect with a preview.
50
51
  */
51
52
  width?: "trigger" | "own";
52
53
  /** The side tried first. The popover flips when the other side has more room. */
53
54
  side?: "below" | "above";
54
55
  };
55
- export declare const placeChoicePopover: (trigger: HTMLElement, popover: HTMLElement, placement?: ChoicePopoverPlacement) => void;
56
+ /**
57
+ * Places the popover under (or above) its trigger. `floor` is the narrowest
58
+ * width it may take, such as the width it already had while open, so filtering
59
+ * the options never makes it narrower.
60
+ */
61
+ export declare const placeChoicePopover: (trigger: HTMLElement, popover: HTMLElement, placement?: ChoicePopoverPlacement, floor?: number) => void;
56
62
  export declare function createChoicePopover(disabled: () => boolean, placement?: () => ChoicePopoverPlacement): {
57
63
  open: () => boolean;
58
64
  setTrigger: Setter<HTMLElement | undefined>;
@@ -100,6 +100,14 @@ export type DetailPanelActionButtonProps = DetailPanelActionBaseProps & DetailPa
100
100
  href?: never;
101
101
  };
102
102
  export type DetailPanelActionProps = DetailPanelActionLinkProps | DetailPanelActionButtonProps;
103
+ /** A row that only shows something, such as a person and their role: the columns of an action, without a command. */
104
+ export type DetailPanelRowProps = {
105
+ title: JSX.Element;
106
+ description?: JSX.Element;
107
+ leading?: JSX.Element;
108
+ trailing?: JSX.Element;
109
+ class?: string;
110
+ };
103
111
  export type DetailPanelSectionProps = DetailPanelSectionBaseProps & ({
104
112
  children?: JSX.Element;
105
113
  actions?: JSX.Element;
@@ -127,6 +135,7 @@ type DetailPanelComponent = ((props: DetailPanelProps) => JSX.Element) & {
127
135
  Group: (props: DetailPanelGroupProps) => JSX.Element;
128
136
  Section: (props: DetailPanelSectionProps) => JSX.Element;
129
137
  Action: (props: DetailPanelActionProps) => JSX.Element;
138
+ Row: (props: DetailPanelRowProps) => JSX.Element;
130
139
  };
131
140
  /** A count chip, or "None yet" for zero; shared by sections and discussions. */
132
141
  export declare const DetailPanelCount: (props: {
@@ -0,0 +1,156 @@
1
+ import { type JSX } from "solid-js";
2
+ import { type AvatarShape } from "../surfaces/Avatar";
3
+ export type DetailPresencePerson = {
4
+ /** Stable key, such as the account id. */
5
+ id: string;
6
+ name: string;
7
+ /** A shorter name for the chip and the line below it, such as the first name. Defaults to `name`. */
8
+ shortName?: string;
9
+ src?: string | null;
10
+ icon?: string;
11
+ /** `square` for agents and service accounts. */
12
+ shape?: AvatarShape;
13
+ /** The person's color, the same as their cursor and comments. Defaults to `personColor(name)`. */
14
+ color?: string;
15
+ /** Writing shows a pen and the person's place; reading shows an eye. */
16
+ activity?: "writing" | "reading";
17
+ /** Where the person is, such as the heading of the section they write in. */
18
+ place?: string;
19
+ /** Short text at the end of the person's row in the full list, such as "2 tabs". */
20
+ trailing?: JSX.Element;
21
+ /** Goes to the person's place. */
22
+ onSelect?: () => void;
23
+ /** The person viewing: the fixed "You" chip at the end, never one of the others. */
24
+ self?: boolean;
25
+ };
26
+ /** `offline` keeps the last known people, pale and without live dots; `unavailable` offers `onRetry`. */
27
+ export type DetailPresenceState = "live" | "loading" | "offline" | "unavailable";
28
+ export type DetailPresenceProps = {
29
+ people: readonly DetailPresencePerson[];
30
+ state?: DetailPresenceState;
31
+ /**
32
+ * The quiet line below the people when it does not say who writes where: alone ("Whoever opens the note appears
33
+ * here"), offline ("Offline · as of 19:24"), or unavailable ("Your changes are still being saved").
34
+ */
35
+ note?: JSX.Element;
36
+ onRetry?: () => void;
37
+ /** One control at the end of the title row, such as "Copy link". */
38
+ actions?: JSX.Element;
39
+ /** Defaults to "Here now". */
40
+ title?: string;
41
+ /** One quiet line below the full list. */
42
+ listHint?: JSX.Element;
43
+ class?: string;
44
+ };
45
+ /**
46
+ * "Here now": who has the object open, what they do, and where. Always two lines tall in every state, so people
47
+ * coming, going, or moving never shift the panel. Chips that do not fit wrap into a hidden line and count as "+n";
48
+ * "+n" and "You" open the full list, which `AvatarStack` shows beside it or as a sheet on phones.
49
+ */
50
+ export declare function DetailPresence(props: DetailPresenceProps): JSX.Element;
51
+ /** A fixed slot at the end of a row for the people working there, such as an outline heading. Always the same width. */
52
+ export declare function DetailPresenceSlot(props: {
53
+ people: readonly DetailPresencePerson[];
54
+ max?: number;
55
+ }): JSX.Element;
56
+ export type DetailAccessEntry = {
57
+ id: string;
58
+ name: string;
59
+ /** Sets the avatar: a person's picture or initials, a group, a service, all signed-in people, or public. */
60
+ kind?: "person" | "group" | "service" | "everyone" | "public";
61
+ src?: string | null;
62
+ /** One quiet word after the name, such as "Service". */
63
+ detail?: JSX.Element;
64
+ /** The role in words, such as "Can edit". */
65
+ role: JSX.Element;
66
+ /** The person viewing; listed as "You". */
67
+ self?: boolean;
68
+ };
69
+ export type DetailAccessProps = {
70
+ entries: readonly DetailAccessEntry[];
71
+ state?: "ready" | "loading" | "error";
72
+ onRetry?: () => void;
73
+ /** Rows before "Show n more". Defaults to 5. */
74
+ limit?: number;
75
+ /** A way to change access, only for people who may; others read the list. */
76
+ manage?: {
77
+ label: string;
78
+ href?: string;
79
+ onClick?: () => void;
80
+ };
81
+ /** A quiet line below the list, such as "Applies to the whole notebook". */
82
+ note?: JSX.Element;
83
+ /** Defaults to "Access". */
84
+ title?: string;
85
+ defaultOpen?: boolean;
86
+ open?: boolean;
87
+ onOpenChange?: (open: boolean) => void;
88
+ class?: string;
89
+ };
90
+ /**
91
+ * Who has access and with which role, read-only. Closed it names the first entries; open it lists `limit` rows and
92
+ * "Show n more". A list that may load later passes `state="loading"` and keeps its place.
93
+ */
94
+ export declare function DetailAccess(props: DetailAccessProps): JSX.Element;
95
+ export type DetailLinkItem = {
96
+ id: string;
97
+ title: string;
98
+ href?: string;
99
+ onClick?: (event: MouseEvent) => void;
100
+ /** Defaults to a document. */
101
+ icon?: string;
102
+ /** Quiet text at the end, such as the other notebook's name. */
103
+ trailing?: JSX.Element;
104
+ };
105
+ export type DetailLinksProps = {
106
+ /** What links here. */
107
+ incoming: readonly DetailLinkItem[];
108
+ /** What this object links to. */
109
+ outgoing: readonly DetailLinkItem[];
110
+ /** Rows per direction before "Show n more". Defaults to 5. */
111
+ limit?: number;
112
+ /** Defaults to "Links". */
113
+ title?: string;
114
+ defaultOpen?: boolean;
115
+ class?: string;
116
+ };
117
+ /** "Linked from" and "Links to" in one section. Without links it is one row: the title and "None yet". */
118
+ export declare function DetailLinks(props: DetailLinksProps): JSX.Element;
119
+ export type DetailProperty = {
120
+ id: string;
121
+ label: JSX.Element;
122
+ value: JSX.Element;
123
+ /** An avatar or icon before the value. */
124
+ leading?: JSX.Element;
125
+ /** Makes the value a link, such as "23 versions" to the version history. */
126
+ href?: string;
127
+ };
128
+ export type DetailPropertiesProps = {
129
+ items: readonly DetailProperty[];
130
+ /** Defaults to "Properties". */
131
+ title?: string;
132
+ icon?: string;
133
+ /** One line for the closed section, such as "412 words · created 12 March by Jana Berger". */
134
+ summary?: JSX.Element;
135
+ /** Open by default only when the properties are the object's main content. */
136
+ defaultOpen?: boolean;
137
+ class?: string;
138
+ };
139
+ /** Facts about the object as label and value rows, such as created, edited, size, and the way to its history. */
140
+ export declare function DetailProperties(props: DetailPropertiesProps): JSX.Element;
141
+ export type DetailTag = {
142
+ id: string;
143
+ label: string;
144
+ /** Where the tag leads, such as everything with that tag. */
145
+ href?: string;
146
+ };
147
+ export type DetailTagsProps = {
148
+ tags: readonly DetailTag[];
149
+ /** Defaults to "Tags". */
150
+ title?: string;
151
+ /** Shown without tags, such as how to add one. */
152
+ emptyHint?: JSX.Element;
153
+ class?: string;
154
+ };
155
+ /** The object's tags as chips; a chip with `href` leads to everything with that tag. */
156
+ export declare function DetailTags(props: DetailTagsProps): JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { type JSX } from "solid-js";
2
+ import { type IconButtonProps } from "../actions/Button";
3
+ /** The one icon for "Details" in every app: a circle, so it never reads as the side panel's rectangle with an arrow. */
4
+ export declare const DETAILS_ICON = "ti ti-info-circle";
5
+ export type DetailsToggleProps = Omit<IconButtonProps, "children" | "variant"> & {
6
+ /** Extra classes for the glyph, such as a text size in a dense toolbar. */
7
+ iconClass?: string;
8
+ };
9
+ /**
10
+ * An icon-only Details button for an app's own toolbar or reader head. It shows the selection fill while its panel
11
+ * is open (`aria-expanded="true"`), without a border or shadow, like `AppWorkspace.Detail`'s own button.
12
+ */
13
+ export declare function DetailsToggle(props: DetailsToggleProps): JSX.Element;
@@ -38,9 +38,16 @@ export declare const setPageTrail: (trail: PageTrailState) => void;
38
38
  * the context carries it; the provider also publishes it into the document,
39
39
  * where browser-rendered parts such as islands read it. Below a provider that
40
40
  * renders in the browser, its `trail` prop is the source: update the prop.
41
+ *
42
+ * `onOwnTitle` runs on the server for each `PageTitle` below that is not a
43
+ * fallback. The host then sets `data-k2b-own-title` on an element around the
44
+ * page, inside the `k2b-ui` root, so the chrome's fallback titles step back.
45
+ * With `data-k2b-title-host` on that element, titles that mount or leave in
46
+ * the browser keep the attribute current.
41
47
  */
42
48
  export declare function PageTrailProvider(props: {
43
49
  trail: PageTrailState | undefined;
50
+ onOwnTitle?: () => void;
44
51
  children: JSX.Element;
45
52
  }): JSX.Element;
46
53
  /** The host's page trail: from the provider while rendering below it, otherwise from the document. */
@@ -0,0 +1,59 @@
1
+ /** Titles and sentences of the shared detail sections: presence, access, links, properties, and tags. */
2
+ declare const detailSectionMessages: import("@k2b/stdlib").Catalog<{
3
+ hereNow: string;
4
+ onlyYou: string;
5
+ you: string;
6
+ writesIn: string;
7
+ writing: string;
8
+ reading: string;
9
+ readingAlong: ({ names, count }: {
10
+ names: string;
11
+ count: number;
12
+ }) => string;
13
+ and: string;
14
+ jumpTo: ({ name, place }: {
15
+ name: string;
16
+ place: string;
17
+ }) => string;
18
+ personWriting: ({ name, place }: {
19
+ name: string;
20
+ place: string;
21
+ }) => string;
22
+ personReading: ({ name }: {
23
+ name: string;
24
+ }) => string;
25
+ everyoneHere: ({ count }: {
26
+ count: number;
27
+ }) => string;
28
+ presenceLoading: string;
29
+ presenceUnavailable: string;
30
+ retry: string;
31
+ access: string;
32
+ accessLoading: string;
33
+ accessFailed: string;
34
+ accessSummary: ({ names, more }: {
35
+ names: string;
36
+ more: number;
37
+ }) => string;
38
+ links: string;
39
+ linkedBy: ({ count }: {
40
+ count: number;
41
+ }) => string;
42
+ linksTo: ({ count }: {
43
+ count: number;
44
+ }) => string;
45
+ linkedBySummary: ({ names, more }: {
46
+ names: string;
47
+ more: number;
48
+ }) => string;
49
+ linksToSummary: ({ names, more }: {
50
+ names: string;
51
+ more: number;
52
+ }) => string;
53
+ properties: string;
54
+ tags: string;
55
+ }>;
56
+ export type DetailSectionMessages = ReturnType<(typeof detailSectionMessages)["resolve"]>["t"];
57
+ export declare const useDetailSectionMessages: () => (() => DetailSectionMessages);
58
+ export declare const checkDetailSectionMessages: () => import("@k2b/stdlib").CatalogIssue[];
59
+ export {};
@@ -11,8 +11,11 @@ export { APP_WORKSPACE_DETAIL_DEFAULT, APP_WORKSPACE_DETAIL_MAX, APP_WORKSPACE_D
11
11
  export { type BottomSheetProps, bottomSheetAdaptiveOptions, bottomSheetOptions, default as BottomSheet } from "./BottomSheet";
12
12
  export type { DataPanelProps } from "./DataPanel";
13
13
  export { DataPanel } from "./DataPanel";
14
- export type { DetailPanelActionButtonProps, DetailPanelActionLinkProps, DetailPanelActionProps, DetailPanelActionSecondary, DetailPanelBodyProps, DetailPanelGroupProps, DetailPanelHeaderProps, DetailPanelProps, DetailPanelSectionProps, DetailPanelSummaryProps, DetailPanelTone, } from "./DetailPanel";
14
+ export type { DetailPanelActionButtonProps, DetailPanelActionLinkProps, DetailPanelActionProps, DetailPanelActionSecondary, DetailPanelBodyProps, DetailPanelGroupProps, DetailPanelHeaderProps, DetailPanelProps, DetailPanelRowProps, DetailPanelSectionProps, DetailPanelSummaryProps, DetailPanelTone, } from "./DetailPanel";
15
15
  export { default as DetailPanel } from "./DetailPanel";
16
+ export type { DetailAccessEntry, DetailAccessProps, DetailLinkItem, DetailLinksProps, DetailPresencePerson, DetailPresenceProps, DetailPresenceState, DetailPropertiesProps, DetailProperty, DetailTag, DetailTagsProps, } from "./DetailSections";
17
+ export { DetailAccess, DetailLinks, DetailPresence, DetailPresenceSlot, DetailProperties, DetailTags } from "./DetailSections";
18
+ export { DETAILS_ICON, DetailsToggle, type DetailsToggleProps } from "./DetailsToggle";
16
19
  export type { DiscussionComposerProps, DiscussionItemProps, DiscussionListProps, DiscussionProps } from "./Discussion";
17
20
  export { default as Discussion } from "./Discussion";
18
21
  export type { FloatingWindowClose, FloatingWindowProps, OpenFloatingWindowOptions, } from "./FloatingWindow";
@@ -9,6 +9,8 @@ export type AvatarRing = "success" | {
9
9
  };
10
10
  /** `square` marks an agent or service account; people stay round. */
11
11
  export type AvatarShape = "circle" | "square";
12
+ /** `person` tints initials and icons by name; `neutral` keeps them gray, such as for someone outside the team. */
13
+ export type AvatarTone = "person" | "neutral";
12
14
  export type AvatarProps = {
13
15
  name: string;
14
16
  src?: string | null;
@@ -19,6 +21,7 @@ export type AvatarProps = {
19
21
  /** Draws a ring with a small transparent gap inside the avatar's own box, so the avatar keeps its size and no container clips the ring. */
20
22
  ring?: AvatarRing;
21
23
  shape?: AvatarShape;
24
+ tone?: AvatarTone;
22
25
  loading?: "eager" | "lazy";
23
26
  class?: string;
24
27
  style?: JSX.CSSProperties | string;
@@ -1,5 +1,5 @@
1
1
  import { type JSX } from "solid-js";
2
- import { type AvatarShape } from "./Avatar";
2
+ import { type AvatarShape, type AvatarTone } from "./Avatar";
3
3
  export type AvatarStackPerson = {
4
4
  /** Stable key, such as the account id. */
5
5
  id: string;
@@ -32,8 +32,27 @@ export type AvatarStackProps = {
32
32
  hint?: JSX.Element;
33
33
  /** Faces before "+n". Defaults to 3. */
34
34
  max?: number;
35
+ /** What the button shows instead of the faces, such as a "+n" chip and the viewer's own chip. */
36
+ trigger?: JSX.Element;
35
37
  class?: string;
36
38
  };
39
+ export type AvatarFacesPerson = Pick<AvatarStackPerson, "name" | "src" | "icon" | "shape"> & {
40
+ tone?: AvatarTone;
41
+ };
42
+ export type AvatarFacesProps = {
43
+ people: readonly AvatarFacesPerson[];
44
+ /** Faces before "+n". Defaults to 3. */
45
+ max?: number;
46
+ /** Everyone the faces stand for when `people` lists only some of them; "+n" counts the rest. */
47
+ total?: number;
48
+ /** `sm` (default) matches the stack button; `md` suits a row or table cell whose text the faces stand beside. */
49
+ size?: "sm" | "md";
50
+ };
51
+ /**
52
+ * The stack's faces and "+n" without its button or list, for a row or link that is already interactive. The faces
53
+ * are decorative: name the people in the surrounding label or a tooltip.
54
+ */
55
+ export declare function AvatarFaces(props: AvatarFacesProps): JSX.Element;
37
56
  /**
38
57
  * A few overlapping faces, then "+n", as one button. It opens the full list of people beside it, or as a bottom sheet
39
58
  * on phones. People with `self` are listed last and never shown in the stack.
@@ -0,0 +1,20 @@
1
+ import { type JSX } from "solid-js";
2
+ /** `add` gains something, `change` alters it, `remove` takes it away, `neutral` names a setting. */
3
+ export type ChangeTone = "add" | "change" | "remove" | "neutral" | "warning";
4
+ export type ChangeListItem = {
5
+ tone: ChangeTone;
6
+ /** A Tabler icon class; defaults to plus, arrows or minus by tone. */
7
+ icon?: string;
8
+ content: JSX.Element;
9
+ /** One quiet line under the content, such as what the change means for others. */
10
+ detail?: JSX.Element;
11
+ };
12
+ export type ChangeListProps = {
13
+ items: readonly ChangeListItem[];
14
+ /** Names the list for assistive technology, such as "What changes". */
15
+ label: string;
16
+ class?: string;
17
+ };
18
+ /** Pending changes before they are saved, one line each, so a person can check them in one look. */
19
+ export declare function ChangeList(props: ChangeListProps): JSX.Element;
20
+ export default ChangeList;
@@ -1,7 +1,9 @@
1
- export type { AvatarProps, AvatarRing, AvatarShape, AvatarSize } from "./Avatar";
1
+ export type { AvatarProps, AvatarRing, AvatarShape, AvatarSize, AvatarTone } from "./Avatar";
2
2
  export { Avatar } from "./Avatar";
3
- export type { AvatarStackPerson, AvatarStackProps } from "./AvatarStack";
4
- export { AvatarStack } from "./AvatarStack";
3
+ export type { AvatarFacesPerson, AvatarFacesProps, AvatarStackPerson, AvatarStackProps } from "./AvatarStack";
4
+ export { AvatarFaces, AvatarStack } from "./AvatarStack";
5
+ export type { ChangeListItem, ChangeListProps, ChangeTone } from "./ChangeList";
6
+ export { ChangeList } from "./ChangeList";
5
7
  export type { DescriptionListItem, DescriptionListProps } from "./DescriptionList";
6
8
  export { DescriptionList } from "./DescriptionList";
7
9
  export type { DotStripProps, DotStripTone } from "./DotStrip";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k2b/ui",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "description": "Production-ready components for SolidJS applications.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -91,13 +91,13 @@
91
91
  "qr-scanner": "1.4.2"
92
92
  },
93
93
  "peerDependencies": {
94
- "@k2b/ssr": "^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0 || ^0.20.0",
94
+ "@k2b/ssr": "^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0",
95
95
  "solid-js": "^1.9.10"
96
96
  },
97
97
  "devDependencies": {
98
98
  "@babel/core": "8.0.6",
99
99
  "@babel/preset-typescript": "8.0.1",
100
- "@k2b/ssr": "0.20.2",
100
+ "@k2b/ssr": "0.21.0",
101
101
  "@types/babel__core": "7.20.5",
102
102
  "@types/bun": "1.4.2",
103
103
  "axe-core": "4.11.0",