@webority/ui-react 0.30.0 → 0.32.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.
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Document drop zone: a drag-and-drop target that hands the chosen file to the page and keeps
3
+ * nothing. Unlike `AppFilePicker` it has no value and shows no preview; the page decides what
4
+ * the file becomes (an upload, a viewer, a parse). A file that fails the type or size check is
5
+ * rejected inline and never reaches `onChange`.
6
+ *
7
+ * @param {object} props
8
+ * @param {(file: File | File[]) => void} props.onChange Single mode: the validated File. Multiple
9
+ * mode: the validated Files of that pick or drop. Not called when nothing passes validation.
10
+ * @param {string} [props.label]
11
+ * @param {string} [props.id] DOM id for the file input and its label's `for` target.
12
+ * @param {boolean} [props.multiple=false] Take several files per pick or drop; `onChange` gets an array.
13
+ * @param {string} [props.accept=""] Accepted file types (the `accept` attribute). Empty takes any file.
14
+ * @param {number} [props.maxSizeMb] Defaults to the shared DEFAULT_MAX_SIZE_MB. 0 means no size
15
+ * limit: nothing is rejected for its size, and the hint names no size.
16
+ * @param {string} [props.error] Message below the zone; also styles the zone as errored.
17
+ * @param {string} [props.hint] Helper text below the zone; an error (the caller's or a rejected
18
+ * pick's) replaces it while it shows.
19
+ * @param {boolean} [props.disabled=false] Blocks click and drop.
20
+ * @param {string} [props.className] Class to apply to the control element, the visible zone.
21
+ * @param {string} [props.fieldClassName] Class to apply to the wrapper field div.
22
+ * @param {object} [props.style] Inline style; lands on the control with `className`.
23
+ */
24
+ export default function AppDropZone({ label, id, onChange, multiple, accept, maxSizeMb, error, hint, disabled, className, fieldClassName, style, ...rest }: {
25
+ onChange: (file: File | File[]) => void;
26
+ label?: string;
27
+ id?: string;
28
+ multiple?: boolean;
29
+ accept?: string;
30
+ maxSizeMb?: number;
31
+ error?: string;
32
+ hint?: string;
33
+ disabled?: boolean;
34
+ className?: string;
35
+ fieldClassName?: string;
36
+ style?: object;
37
+ }): import("react").JSX.Element;
@@ -6,7 +6,8 @@
6
6
  * choice via onPick — a File|null in single mode, a File[] in multiple mode.
7
7
  *
8
8
  * Not just images: widen `accept` (e.g. "image/*,application/pdf") and non-image files show a
9
- * file-type icon instead of a thumbnail.
9
+ * file-type icon instead of a thumbnail. A single PDF shows its first page instead, drawn by the
10
+ * lazily loaded viewer entry; the icon stays if the page cannot be drawn.
10
11
  *
11
12
  * @param {object} props
12
13
  * @param {string} [props.label]
@@ -13,15 +13,19 @@ import "@webority/ui-elements";
13
13
  * that needs a decision first (a reason for a lost deal) opens the product's own AppModal from
14
14
  * `onMove` and settles the promise with the modal's outcome.
15
15
  *
16
- * Below the md breakpoint the board shows one column per screen with a column switcher above it;
17
- * the board scrolls inside itself, so the page never scrolls sideways.
16
+ * Below the md breakpoint the board shows one column per screen with a column switcher above it
17
+ * that stays at the top of the viewport; the board scrolls inside itself, so the page never
18
+ * scrolls sideways.
18
19
  *
19
20
  * @param {object} props
20
21
  * @param {{ key: string, title: string, tone?: 'neutral'|'primary'|'info'|'success'|'warning'|'danger',
21
22
  * href?: string, summary?: import('react').ReactNode | ((cards: object[]) => import('react').ReactNode),
22
- * acceptFrom?: string[], collapsible?: boolean, collapsed?: boolean, emptyText?: string }[]} props.columns
23
+ * acceptFrom?: string[], collapsible?: boolean, collapsed?: boolean, emptyText?: string,
24
+ * visibleLimit?: number }[]} props.columns
23
25
  * The columns, left to right. `acceptFrom` lists the only columns this one takes cards from;
24
26
  * `collapsible` columns fold to a strip, remembered per `boardId`; `collapsed` is the first state.
27
+ * `visibleLimit` shows the first N cards the filter lets through, with "Show N more" for the
28
+ * rest; the count still covers every card, and a card dropped there always shows.
25
29
  * @param {object[]} props.cards Every card on the board.
26
30
  * @param {(card: object) => import('react').ReactNode} props.renderCard The card's content.
27
31
  * @param {(card: object) => string} [props.getCardKey] Default `card.key ?? card.id`.
@@ -29,6 +33,9 @@ import "@webority/ui-elements";
29
33
  * @param {(card: object) => number} [props.getCardValue] The number a computed summary adds up.
30
34
  * @param {(card: object) => string} [props.cardLabel] The card's accessible name, used in announcements.
31
35
  * @param {(card: object) => boolean} [props.isCardLocked] A locked card cannot be moved.
36
+ * @param {(attempt: { card: object, key: string, reason: 'locked'|'readonly' }) => void} [props.onLocked]
37
+ * Someone tried to pick up a card that cannot move (a locked card, or any card on a read-only
38
+ * board); show your own message. Screen readers are told either way.
32
39
  * @param {(move: { card: object, key: string, from: string, to: string, index: number }) => void | Promise<unknown>} [props.onMove]
33
40
  * @param {(card: object, from: string, to: string) => boolean | string} [props.accept] Refuse a move:
34
41
  * false, or a string saying why (shown in the column while the card is carried).
@@ -37,13 +44,14 @@ import "@webority/ui-elements";
37
44
  * @param {string} [props.ariaLabel='Board'] Accessible name of the board region.
38
45
  * @param {string} [props.emptyText='Nothing here'] Text of an empty column.
39
46
  * @param {boolean} [props.readOnly=false] No card can move.
47
+ * @param {boolean} [props.swipeHint=false] On phones, a "Swipe sideways or tap a column" line under the switcher.
40
48
  * @param {'number'|'currency'|'compact'} [props.summaryFormat] Each column's summary becomes the sum
41
49
  * of its visible cards' `getCardValue`, in this format.
42
50
  * @param {'rupees'|'paise'} [props.summaryUnit='rupees'] The unit of the card values.
43
51
  * @param {string} [props.className]
44
52
  * @param {string} [props.id] The board's id; the column, body and help ids derive from it. Generated when omitted.
45
53
  */
46
- export default function AppKanban({ columns, cards, renderCard, getCardKey, getCardColumn, getCardValue, cardLabel, isCardLocked, onMove, accept, filter, boardId, ariaLabel, emptyText, readOnly, summaryFormat, summaryUnit, className, id, ...rest }: {
54
+ export default function AppKanban({ columns, cards, renderCard, getCardKey, getCardColumn, getCardValue, cardLabel, isCardLocked, onLocked, onMove, accept, filter, boardId, ariaLabel, emptyText, readOnly, swipeHint, summaryFormat, summaryUnit, className, id, ...rest }: {
47
55
  columns: {
48
56
  key: string;
49
57
  title: string;
@@ -54,6 +62,7 @@ export default function AppKanban({ columns, cards, renderCard, getCardKey, getC
54
62
  collapsible?: boolean;
55
63
  collapsed?: boolean;
56
64
  emptyText?: string;
65
+ visibleLimit?: number;
57
66
  }[];
58
67
  cards: object[];
59
68
  renderCard: (card: object) => import('react').ReactNode;
@@ -62,6 +71,11 @@ export default function AppKanban({ columns, cards, renderCard, getCardKey, getC
62
71
  getCardValue?: (card: object) => number;
63
72
  cardLabel?: (card: object) => string;
64
73
  isCardLocked?: (card: object) => boolean;
74
+ onLocked?: (attempt: {
75
+ card: object;
76
+ key: string;
77
+ reason: 'locked' | 'readonly';
78
+ }) => void;
65
79
  onMove?: (move: {
66
80
  card: object;
67
81
  key: string;
@@ -75,6 +89,7 @@ export default function AppKanban({ columns, cards, renderCard, getCardKey, getC
75
89
  ariaLabel?: string;
76
90
  emptyText?: string;
77
91
  readOnly?: boolean;
92
+ swipeHint?: boolean;
78
93
  summaryFormat?: 'number' | 'currency' | 'compact';
79
94
  summaryUnit?: 'rupees' | 'paise';
80
95
  className?: string;
@@ -166,8 +166,10 @@ export type SearchShape = {
166
166
  * each item's `active` decides, as before.
167
167
  *
168
168
  * @param {object} props
169
- * @param {{ label?: string, items: NavItemShape[] }[]} props.groups Nav groups, in order.
170
- * Groups after the first are separated by a rule. A group left with no items is not rendered.
169
+ * @param {{ label?: string, items: NavItemShape[], after?: import('react').ReactNode }[]} props.groups Nav groups, in order.
170
+ * Groups after the first are separated by a rule. A group left with no items is not rendered,
171
+ * and neither is its `after`. `after` is a node rendered right after that group's links (an
172
+ * "add a space" row, a help note); it is hidden on the collapsed rail and shown in the drawer.
171
173
  * @param {import('react').ReactNode} [props.brand] The logo row at the top of the sidebar.
172
174
  * @param {import('react').ReactNode} [props.sidebarStart] Between the brand row and the nav —
173
175
  * a workspace/tenant switcher, an environment badge. Hidden on the collapsed rail.
@@ -198,6 +200,7 @@ export default function AppShell({ groups, brand, sidebarStart, sidebarStartComp
198
200
  groups: {
199
201
  label?: string;
200
202
  items: NavItemShape[];
203
+ after?: import('react').ReactNode;
201
204
  }[];
202
205
  brand?: import('react').ReactNode;
203
206
  sidebarStart?: import('react').ReactNode;
@@ -0,0 +1,32 @@
1
+ import "@webority/ui-elements";
2
+ /**
3
+ * A step-by-step product tour over the shared `<wui-tour>` element: the page is dimmed except
4
+ * around the step's target, and a card holds the step text with Back, Next and Skip. Steps are
5
+ * data, anchored to elements by CSS selector. A step whose target is missing or hidden is
6
+ * dropped.
7
+ *
8
+ * Accessibility: focus moves into the card on open, stays there while the tour runs, and returns
9
+ * to where it was on close; each step is announced; Escape skips the tour; the arrow keys move
10
+ * between steps. On a phone the card sits on the side of the target with room and never covers it.
11
+ *
12
+ * Set `open` to run the tour and set it back to false from `onClose`. Pass a `seenStore` to
13
+ * remember that a person has seen it: it is asked before showing and written when the tour
14
+ * finishes or is skipped. `createLocalSeenStore()` (from `@webority/ui-elements`) keeps that in
15
+ * the browser; a product that keeps it on its server passes its own `{ isSeen, markSeen }`.
16
+ *
17
+ * @param {object} props
18
+ * @param {boolean} props.open Runs the tour. Set it back to false from `onClose`.
19
+ * @param {(reason: 'finished'|'skipped'|'alreadySeen'|'noTargets') => void} props.onClose Called when the tour ends.
20
+ * `finished`: the person stepped past the last step; `skipped`: Skip or Escape (both marked
21
+ * seen); `alreadySeen`: the store says it was seen, so nothing showed; `noTargets`: no step had
22
+ * a visible target, so nothing showed (not marked seen).
23
+ * @param {string} props.tourId Names the tour in the seen store.
24
+ * @param {{ target: string, title?: string, description: string }[]} props.steps `target` is a CSS selector.
25
+ * @param {{ isSeen: (tourId: string) => Promise<boolean>, markSeen: (tourId: string) => Promise<void> }} [props.seenStore]
26
+ * Read through a ref, so an inline object does not restart a running tour.
27
+ * @param {(step: object, index: number) => void | Promise<void>} [props.onBeforeStep] Runs before each step's target is looked up, awaited. Use it to open a menu or switch a tab so the target is visible.
28
+ * @param {{ back?: string, next?: string, skip?: string, done?: string }} [props.labels] Button text; defaults Back, Next, Skip, Done.
29
+ * @param {string} [props.className]
30
+ */
31
+ declare const AppTour: import("react").ForwardRefExoticComponent<import("react").RefAttributes<any>>;
32
+ export default AppTour;
@@ -1,4 +1,4 @@
1
- export { postedMasked } from "@webority/ui-elements";
1
+ export { createLocalSeenStore, postedMasked } from "@webority/ui-elements";
2
2
  export { default as AppAccordion } from "./components/AppAccordion.jsx";
3
3
  export { default as AppActionIcon } from "./components/AppActionIcon.jsx";
4
4
  export { default as AppAlert } from "./components/AppAlert.jsx";
@@ -8,7 +8,6 @@ export { default as AppAvatar } from "./components/AppAvatar.jsx";
8
8
  export { default as AppAvatarGroup } from "./components/AppAvatarGroup.jsx";
9
9
  export { default as AppBadge } from "./components/AppBadge.jsx";
10
10
  export { default as AppBanner } from "./components/AppBanner.jsx";
11
- export { default as AppBarChart } from "./components/AppBarChart.jsx";
12
11
  export { default as AppBreadcrumbs } from "./components/AppBreadcrumbs.jsx";
13
12
  export { default as AppButton } from "./components/AppButton.jsx";
14
13
  export { default as AppCalendar } from "./components/AppCalendar.jsx";
@@ -35,6 +34,7 @@ export { default as AppDatePicker } from "./components/AppDatePicker.jsx";
35
34
  export { default as AppDateRangePicker } from "./components/AppDateRangePicker.jsx";
36
35
  export { default as AppDescriptions } from "./components/AppDescriptions.jsx";
37
36
  export { default as AppDropdown } from "./components/AppDropdown.jsx";
37
+ export { default as AppDropZone } from "./components/AppDropZone.jsx";
38
38
  export { default as AppEmptyState } from "./components/AppEmptyState.jsx";
39
39
  export { default as AppErrorSummary } from "./components/AppErrorSummary.jsx";
40
40
  export { default as AppFileAttachment } from "./components/AppFileAttachment.jsx";
@@ -51,7 +51,6 @@ export { default as AppInfoTip } from "./components/AppInfoTip.jsx";
51
51
  export { default as AppInput } from "./components/AppInput.jsx";
52
52
  export { default as AppKanban } from "./components/AppKanban.jsx";
53
53
  export { default as AppKpiTile } from "./components/AppKpiTile.jsx";
54
- export { default as AppLineChart } from "./components/AppLineChart.jsx";
55
54
  export { default as AppLink } from "./components/AppLink.jsx";
56
55
  export { default as AppLogoPicker } from "./components/AppLogoPicker.jsx";
57
56
  export { default as AppMeter } from "./components/AppMeter.jsx";
@@ -101,6 +100,7 @@ export { default as AppTimePicker } from "./components/AppTimePicker.jsx";
101
100
  export { default as AppToast } from "./components/AppToast.jsx";
102
101
  export { default as AppToolbar } from "./components/AppToolbar.jsx";
103
102
  export { default as AppTooltip } from "./components/AppTooltip.jsx";
103
+ export { default as AppTour } from "./components/AppTour.jsx";
104
104
  export { default as AppTreeView } from "./components/AppTreeView.jsx";
105
105
  export { default as AppWizard } from "./components/AppWizard.jsx";
106
106
  export { default as AppWorkspaceSwitcher } from "./components/AppWorkspaceSwitcher.jsx";
@@ -108,6 +108,7 @@ export { MODAL_ICONS } from "./components/ModalIcons.jsx";
108
108
  export { dismissAll, errorToast, toast } from "./components/toast.js";
109
109
  export { buildListQuery, parseListQuery } from "./lib/listQuery.js";
110
110
  export { useCommandPaletteShortcut } from "./lib/useCommandPaletteShortcut.js";
111
+ export { useFloatingStack } from "./lib/useFloatingStack.js";
111
112
  export { useListQuery } from "./lib/useListQuery.js";
112
113
  export { usePagination } from "./lib/usePagination.js";
113
114
  export { useTableView } from "./lib/useTableView.js";
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The one fixed container in a bottom corner that floating buttons stack in, so two of them
3
+ * (the chat launcher and the report-an-issue button) sit one above the other with a gap and
4
+ * never overlap. Render into it with `createPortal`, wrapping each button in a
5
+ * `.wui-floating-stack-item` (`--primary` sits in the corner, `--secondary` stacks above it).
6
+ *
7
+ * The container is created for the first caller in a corner and removed with the last, so the
8
+ * hook belongs in a component that renders the button. Returns null until the container exists
9
+ * (the first render), so render nothing then.
10
+ *
11
+ * @param {"end"|"start"} [position="end"] The bottom corner the stack is pinned to.
12
+ * @param {boolean} [enabled=true] Hooks cannot be called conditionally; pass false when this
13
+ * render has nothing to put in the stack, and no container is created or held.
14
+ * @returns {HTMLElement|null} The container to portal into.
15
+ */
16
+ export declare function useFloatingStack(position?: "end" | "start", enabled?: boolean): HTMLElement | null;