@beautinique/frontend-components 1.0.3 → 1.0.4
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.
- package/README.md +4 -5
- package/dist/toast/index.cjs +3 -4
- package/dist/toast/index.cjs.map +1 -1
- package/dist/toast/index.js +3 -4
- package/dist/toast/index.js.map +1 -1
- package/dist/ui/Button.d.cts.map +1 -1
- package/dist/ui/Button.d.ts.map +1 -1
- package/dist/ui/index.cjs +3 -4
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.js +3 -4
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -12,7 +12,6 @@ npm install @beautinique/frontend-components @beautinique/frontend-styles @iconi
|
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
Peer dependencies: `react`, `react-dom`, `@iconify/react`, `@beautinique/frontend-styles`.
|
|
15
|
-
It needs `tailwind-merge` too, which comes with it.
|
|
16
15
|
|
|
17
16
|
## Setup (once per app)
|
|
18
17
|
|
|
@@ -73,10 +72,10 @@ const edit = (
|
|
|
73
72
|
);
|
|
74
73
|
```
|
|
75
74
|
|
|
76
|
-
- **Classes you give
|
|
77
|
-
|
|
78
|
-
classes
|
|
79
|
-
`
|
|
75
|
+
- **Classes you give are added after the button's own and none of its own is removed.** To win over
|
|
76
|
+
one of them make it important with `!`: `className="rounded-md! px-2! lg:px-2!"`. The button has
|
|
77
|
+
classes for large screens (`lg:px-5`, `lg:py-4`, `xl:text-base`), they are other classes than
|
|
78
|
+
`px-4` and so on, so to change the padding on every screen give the `lg:` one too.
|
|
80
79
|
- **`ref`** is the `<button>` itself: `<Button ref={buttonRef} ... />`.
|
|
81
80
|
- A button with only an icon does not compile without `aria-label` or `aria-labelledby` in
|
|
82
81
|
`buttonProps`.
|
package/dist/toast/index.cjs
CHANGED
|
@@ -4,7 +4,6 @@ var nanoid = require('nanoid');
|
|
|
4
4
|
var zustand = require('zustand');
|
|
5
5
|
var react$1 = require('@iconify/react');
|
|
6
6
|
var react = require('react');
|
|
7
|
-
var tailwindMerge = require('tailwind-merge');
|
|
8
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
9
8
|
|
|
10
9
|
var __defProp = Object.defineProperty;
|
|
@@ -134,14 +133,14 @@ var Button = /* @__PURE__ */ __name(({
|
|
|
134
133
|
buttonProps,
|
|
135
134
|
ref
|
|
136
135
|
}) => (
|
|
137
|
-
//
|
|
138
|
-
//
|
|
136
|
+
// The classes that are given come last but do not remove the button's own: to win over one of
|
|
137
|
+
// them give it with `!` (`rounded-md!`), the way the toast's button does.
|
|
139
138
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
140
139
|
"button",
|
|
141
140
|
{
|
|
142
141
|
...buttonProps,
|
|
143
142
|
ref,
|
|
144
|
-
className:
|
|
143
|
+
className: `${BASE_CSS} ${getButtonCss(pattern)} ${className} ${buttonProps?.className ?? ""}`,
|
|
145
144
|
type: buttonProps?.type ?? "button",
|
|
146
145
|
children: [
|
|
147
146
|
leftIcon && /* @__PURE__ */ jsxRuntime.jsx(react$1.Icon, { ...leftIcon }),
|
package/dist/toast/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/constants.ts","../../src/toast/toast.store.ts","../../src/toast/toast-icons.ts","../../src/lib/button.ts","../../src/ui/Button.tsx","../../src/toast/toaster.ts","../../src/toast/uploads.ts","../../src/toast/ToastContainer.tsx"],"names":["create","nanoid","addCollection","jsxs","twMerge","jsx","Icon","remove","useState","useRef","useCallback","useEffect","memo"],"mappings":"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","file":"index.cjs","sourcesContent":["export const TOOLTIP_GAP = 15 as const;\nexport const TOOLTIP_ANIMATION_DURATION = 400 as const;\n/** The least space a tooltip keeps between itself and the edge of the window. */\nexport const TOOLTIP_VIEWPORT_MARGIN = 8 as const;\n/** The arrow stays at least this far from the ends of the tooltip (its own size and the rounded corner). */\nexport const TOOLTIP_ARROW_INSET = 16 as const;\n\nexport const TOAST_TYPES = [\n 'success',\n 'error',\n 'warning',\n 'progress',\n 'uploads',\n 'loading',\n 'default',\n 'custom',\n] as const;\n\nexport const TOAST_TYPE = Object.fromEntries(TOAST_TYPES.map((type) => [type, type])) as {\n [K in (typeof TOAST_TYPES)[number]]: K;\n};\n","import { nanoid } from 'nanoid';\nimport { create } from 'zustand';\n\nimport { TOAST_TYPE } from '../lib/constants.js';\nimport type { IToastStore } from './types.js';\n\nconst useToastStore = create<IToastStore>((set) => ({\n toasts: [],\n\n add: (toast) => {\n const id = nanoid();\n\n set((state) => ({ toasts: [...state.toasts, { ...toast, id }] }));\n\n return id; // return the id of the toast for removal\n },\n\n update: {\n progress: (id, progress) => {\n set((state) => ({\n toasts: state.toasts.map((toast) => (toast.id === id ? { ...toast, progress } : toast)),\n }));\n },\n\n uploadItem: (id, itemId, patch) => {\n set((state) => ({\n toasts: state.toasts.map((toast) =>\n toast.id === id && toast.type === TOAST_TYPE.uploads\n ? {\n ...toast,\n items: toast.items.map((item) =>\n item.id === itemId ? { ...item, ...patch } : item,\n ),\n }\n : toast,\n ),\n }));\n },\n },\n\n remove: (id) => {\n set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));\n },\n}));\n\nexport { useToastStore };\n","import { addCollection, type IconifyJSON } from '@iconify/react';\n\n/*\n * Iconify downloads an icon's SVG from its API the first time the icon is shown, and keeps it in\n * memory. A toast's icon is very often needed for the first time exactly when the download cannot\n * work: the \"You're offline\" toast, or the error toast of a request that failed because there is no\n * internet. Those icons are bundled here, so every toast has its icon without a network.\n *\n * Add an icon here when a toast starts using one (see `cardConfig` in `components/ui/Toaster.tsx`).\n * The data is what `https://api.iconify.design/<prefix>.json?icons=<name>` answers.\n */\nconst TOAST_ICON_SETS: IconifyJSON[] = [\n {\n prefix: 'solar',\n width: 24,\n height: 24,\n icons: {\n // warning and error toasts\n 'danger-triangle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><path d=\"M5.31171 10.7615C8.23007 5.58716 9.68925 3 12 3C14.3107 3 15.7699 5.58716 18.6883 10.7615L19.0519 11.4063C21.4771 15.7061 22.6897 17.856 21.5937 19.428C20.4978 21 17.7864 21 12.3637 21H11.6363C6.21356 21 3.50217 21 2.40626 19.428C1.31034 17.856 2.52291 15.7061 4.94805 11.4063L5.31171 10.7615Z\"/><path d=\"M12 8V13\"/><path stroke-linejoin=\"round\" d=\"M12 16H12.0001\"/></g>',\n },\n // success toast\n 'check-circle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path stroke-linejoin=\"round\" d=\"M8.5 12.5L10.5 14.5L15.5 9.5\"/></g>',\n },\n // an upload that is waiting its turn, in an uploads toast\n 'clock-circle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path stroke-linejoin=\"round\" d=\"M12 8V12L14.5 14.5\"/></g>',\n },\n // default and custom toasts\n 'info-circle-outline': {\n body: '<g fill=\"currentColor\"><path d=\"M12 17.75C12.4142 17.75 12.75 17.4142 12.75 17V11C12.75 10.5858 12.4142 10.25 12 10.25C11.5858 10.25 11.25 10.5858 11.25 11V17C11.25 17.4142 11.5858 17.75 12 17.75Z\"/><path d=\"M12 7C12.5523 7 13 7.44772 13 8C13 8.55228 12.5523 9 12 9C11.4477 9 11 8.55228 11 8C11 7.44772 11.4477 7 12 7Z\"/><path fill-rule=\"evenodd\" d=\"M1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12ZM12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.9371 2.75 12 2.75Z\" clip-rule=\"evenodd\"/></g>',\n },\n },\n },\n {\n prefix: 'beautinique',\n width: 24,\n height: 24,\n icons: {\n /*\n * The spinner of the loading toast and of an upload that is going on. It turns itself, inside\n * the svg (`animateTransform`, around the centre of the ring), instead of being turned by a\n * css `animate-spin` on the svg: the browser then draws the ring again at the exact angle on\n * every frame. A css turn rotates a picture of the whole svg, and on a screen with a scaling of\n * 125% an icon of 20px is 25 device pixels, so the middle of that picture is half a pixel off\n * and the ring jumps up and down a little while it turns. Do not add `animate-spin` to it.\n */\n 'loading-spin': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M17 3.34A10 10 0 1 0 22 12\"><animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\"/></path>',\n },\n },\n },\n {\n prefix: 'lucide',\n width: 24,\n height: 24,\n icons: {\n // the close button of a closable toast\n x: {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M18 6L6 18M6 6l12 12\"/>',\n },\n },\n },\n];\n\n/**\n * Registers the icons above with Iconify (calling it again is harmless). It is a function that\n * `ToastContainer` calls, and not something that happens when this file is imported, on purpose: a\n * bare `import './toast-icons.js'` is dropped by the bundler when the package's `sideEffects` field\n * does not list the file (the build says \"ignored-bare-import\"), and then the icons are missing.\n */\nexport const registerToastIcons = () => {\n for (const iconSet of TOAST_ICON_SETS) addCollection(iconSet);\n};\n\n/** Every icon name registered above, e.g. `solar:danger-triangle-linear`. */\nexport const TOAST_ICON_NAMES = TOAST_ICON_SETS.flatMap(({ prefix, icons }) =>\n Object.keys(icons).map((name) => `${prefix}:${name}`),\n);\n","import type { IButton } from '../types/component.js';\n\ntype TPattern = IButton['pattern'];\n\n// A `Record`: adding a pattern to the type is a type error here until it has a look.\nconst PATTERN_CSS: Record<TPattern, string> = {\n primary: 'text-white bg-sky-blue-burst shadow-primary-btn hover:shadow-primary-btn-hover',\n secondary:\n 'text-secondary-invert bg-secondary shadow-secondary-btn hover:shadow-secondary-btn-hover',\n tertiary: 'text-tertiary-invert bg-tertiary shadow-tertiary-btn hover:shadow-tertiary-btn-hover',\n outline: 'text-primary border border-primary shadow-outline-btn hover:shadow-outline-btn-hover',\n transparent: 'bg-transparent border border-primary/30 text-secondary',\n};\n\n/** The look of a pattern; a pattern nobody knows (from code that is not type checked) is transparent. */\nexport const getButtonCss = (pattern: TPattern) =>\n Object.hasOwn(PATTERN_CSS, pattern) ? PATTERN_CSS[pattern] : PATTERN_CSS.transparent;\n","import { Icon } from '@iconify/react';\nimport { twMerge } from 'tailwind-merge';\n\nimport { getButtonCss } from '../lib/button.js';\nimport type { IButton } from '../types/component.js';\n\nconst BASE_CSS =\n 'group flex w-full cursor-pointer items-center justify-center gap-1 rounded-lg px-4 py-3 text-sm leading-4 transition-all duration-300 disabled:cursor-not-allowed disabled:opacity-85 lg:px-5 lg:py-4 xl:text-base';\n\nexport const Button = ({\n pattern,\n content,\n className = '',\n leftIcon,\n rightIcon,\n buttonProps,\n ref,\n}: IButton) => (\n // A class that is given wins over the one it clashes with (`rounded-md` over `rounded-lg`),\n // with no `!`; one for another screen size (`lg:px-5`) is a different class and stays.\n <button\n {...buttonProps}\n ref={ref}\n className={twMerge(BASE_CSS, getButtonCss(pattern), className, buttonProps?.className)}\n type={buttonProps?.type ?? 'button'}\n >\n {leftIcon && <Icon {...leftIcon} />}\n {typeof content === 'object' ? <Icon {...content} /> : content}\n {rightIcon && <Icon {...rightIcon} />}\n </button>\n);\n","import { TOAST_TYPE } from '../lib/constants.js';\nimport { useToastStore } from './toast.store.js';\nimport type {\n ICustomToast,\n IDefaultToast,\n ILoadingToast,\n IProgressToast,\n IUploadItem,\n IUploadsToast,\n TProgressToastOptions,\n} from './types.js';\n\nconst { add, update, remove } = useToastStore.getState();\nexport const toaster = {\n success: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.success }),\n error: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.error }),\n warning: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.warning }),\n default: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.default }),\n loading: (data: Omit<ILoadingToast, 'type'>) => add({ ...data, type: TOAST_TYPE.loading }),\n custom: (data: ICustomToast) => add(data),\n progress: {\n start: (data: Omit<IProgressToast, 'type'>) => add({ ...data, type: TOAST_TYPE.progress }),\n update: (toastId: string, progress: number) => {\n update.progress(toastId, progress);\n },\n end: (toastId: string) => {\n remove(toastId);\n },\n },\n uploads: {\n start: (data: Omit<IUploadsToast, 'type'>) => add({ ...data, type: TOAST_TYPE.uploads }),\n update: (toastId: string, itemId: string, patch: Partial<Omit<IUploadItem, 'id'>>) => {\n update.uploadItem(toastId, itemId, patch);\n },\n },\n remove: (toastId: string) => {\n remove(toastId);\n },\n};\n\nexport const withProgressToast = async <T>({\n title,\n description,\n request,\n}: TProgressToastOptions<T>): Promise<T> => {\n const toastId = toaster.progress.start({ title, description, progress: 0 });\n\n try {\n const response = await request((event) => {\n if (!event.total) return;\n\n toaster.progress.update(toastId, Math.round((event.loaded * 100) / event.total));\n });\n\n toaster.progress.update(toastId, 100);\n\n return response;\n } finally {\n toaster.progress.end(toastId);\n }\n};\n","import { toaster } from './toaster.js';\nimport type {\n IUploadGroup,\n IUploadItem,\n IUploadItemHandle,\n TUploadItemStatus,\n TUploadProgressHandler,\n} from './types.js';\n\nconst sum = (numbers: number[]) => numbers.reduce((total, value) => total + value, 0);\n\n/* ===================== WHAT THE TOAST SHOWS ===================== */\n\nexport const isUploadItemSettled = ({ status }: Pick<IUploadItem, 'status'>) =>\n status === 'success' || status === 'error';\n\n/**\n * How many files of an upload are through. An upload is one request, so a file is known to be\n * through only once the server has answered; until then the files that were completely sent count,\n * except the last one (it may still be on its way to the storage). A failed upload has none.\n */\nexport const getUploadItemFilesDone = ({\n status,\n loaded,\n fileSizes,\n}: Pick<IUploadItem, 'status' | 'loaded' | 'fileSizes'>) => {\n if (status === 'success') return fileSizes.length;\n if (status !== 'uploading') return 0;\n\n let sent = 0;\n let bytes = 0;\n\n for (const size of fileSizes) {\n bytes += size;\n\n if (bytes > loaded) break;\n\n sent += 1;\n }\n\n return Math.min(sent, Math.max(fileSizes.length - 1, 0));\n};\n\n/** How far one upload is, 0 to 100. 100 is only for an upload the server has answered. */\nexport const getUploadItemPercent = ({\n status,\n loaded,\n total,\n}: Pick<IUploadItem, 'status' | 'loaded' | 'total'>) => {\n if (status === 'success') return 100;\n if (status === 'pending' || total <= 0) return 0;\n\n return Math.min(99, Math.round((Math.min(loaded, total) * 100) / total));\n};\n\nexport interface IUploadsSummary {\n /** Overall progress by bytes, 0 to 100. 100 only when every upload has succeeded. */\n percent: number;\n filesDone: number;\n filesTotal: number;\n /** How many uploads failed. */\n failed: number;\n /** Every upload has either succeeded or failed. */\n isSettled: boolean;\n}\n\nexport const getUploadsSummary = (items: IUploadItem[]): IUploadsSummary => {\n const failed = items.filter(({ status }) => status === 'error').length;\n const isSettled = items.every(isUploadItemSettled);\n const bytesTotal = sum(items.map(({ total }) => total));\n const bytesDone = sum(\n items.map((item) =>\n item.status === 'success' ? item.total : Math.min(item.loaded, item.total),\n ),\n );\n\n let percent = bytesTotal > 0 ? Math.round((bytesDone * 100) / bytesTotal) : 0;\n\n if (isSettled && failed === 0) percent = 100;\n else percent = Math.min(percent, 99);\n\n return {\n percent,\n filesDone: sum(items.map(getUploadItemFilesDone)),\n filesTotal: sum(items.map(({ fileSizes }) => fileSizes.length)),\n failed,\n isSettled,\n };\n};\n\n/* ===================== FILES ===================== */\n\n/** The files of a FormData, in the order they are sent. */\nexport const getFormDataFiles = (data: FormData, key = 'files'): File[] =>\n data.getAll(key).filter((value): value is File => value instanceof File);\n\n/* ===================== THE TOAST OF A GROUP OF UPLOADS ===================== */\n\ninterface IUploadGroupOptions {\n title: string;\n description?: string;\n items: { id: string; label: string; files: File[] }[];\n}\n\n/**\n * Opens one toast for the uploads of `items`. It closes by itself a moment after every upload is\n * over. Returns nothing when there is nothing to upload, so no empty toast is shown.\n */\nexport const createUploadsToast = ({\n title,\n description,\n items,\n}: IUploadGroupOptions): IUploadGroup | undefined => {\n if (items.length === 0) return undefined;\n\n const statuses = new Map<string, TUploadItemStatus>(items.map(({ id }) => [id, 'pending']));\n\n const toastId = toaster.uploads.start({\n title,\n description,\n items: items.map(({ id, label, files }) => {\n const fileSizes = files.map(({ size }) => size);\n\n return { id, label, status: 'pending', loaded: 0, total: sum(fileSizes), fileSizes };\n }),\n });\n\n const patch = (id: string, changes: Partial<Omit<IUploadItem, 'id'>>) => {\n if (changes.status) statuses.set(id, changes.status);\n\n toaster.uploads.update(toastId, id, changes);\n };\n\n return {\n item: (id) => ({\n run: async (request) => {\n patch(id, { status: 'uploading' });\n\n try {\n const result = await request((event) => {\n // The browser says nothing about the total for some requests: keep the size estimate then.\n if (!event.total) return;\n\n patch(id, { loaded: event.loaded, total: event.total });\n });\n\n patch(id, { status: 'success' });\n\n return result;\n } catch (error) {\n patch(id, { status: 'error' });\n\n throw error;\n }\n },\n }),\n\n end: () => {\n for (const [id, status] of statuses) {\n if (status === 'pending' || status === 'uploading') patch(id, { status: 'error' });\n }\n },\n };\n};\n\n/** The toast for a single request that uploads several files at once. */\nexport const withUploadsToast = async <T>({\n title,\n description,\n files,\n request,\n}: {\n title: string;\n description?: string;\n files: File[];\n request: (onProgress: TUploadProgressHandler) => Promise<T>;\n}): Promise<T> => {\n const group = createUploadsToast({\n title,\n description,\n items: files.length > 0 ? [{ id: 'files', label: description ?? title, files }] : [],\n });\n\n if (!group) return request(() => undefined);\n\n try {\n return await group.item('files').run(request);\n } finally {\n group.end();\n }\n};\n\n/**\n * Runs the uploads of several fields (e.g. the images of each editor of a form step) behind one\n * toast with a row for every field that has files. `run` is called for every field, with the row of\n * that field to give to its upload (nothing when the toast has no row for it). Every upload is\n * waited for, so none is shown as failed just because another one failed; if any failed, the first\n * error is thrown once all are over.\n */\nexport const runUploadsInToast = async <TId extends string, TResult>({\n title,\n description,\n uploads,\n run,\n}: {\n title: string;\n description?: string;\n uploads: { id: TId; label: string; files: File[] }[];\n run: (id: TId, progress: IUploadItemHandle | undefined) => Promise<TResult>;\n}): Promise<Record<TId, TResult>> => {\n const group = createUploadsToast({\n title,\n description,\n items: uploads.filter(({ files }) => files.length > 0),\n });\n\n const settled = await Promise.allSettled(uploads.map(({ id }) => run(id, group?.item(id))));\n\n group?.end();\n\n const results = {} as Record<TId, TResult>;\n\n settled.forEach((result, index) => {\n if (result.status === 'fulfilled') results[uploads[index].id] = result.value;\n });\n\n const failure = settled.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n );\n\n if (failure) {\n throw failure.reason instanceof Error ? failure.reason : new Error('Upload failed');\n }\n\n return results;\n};\n","import { Icon } from '@iconify/react';\nimport { type ComponentProps, memo, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { TOAST_TYPE } from '../lib/constants.js';\nimport type { IClassName } from '../types/component.js';\nimport { Button } from '../ui/Button.js';\nimport { registerToastIcons } from './toast-icons.js';\nimport { useToastStore } from './toast.store.js';\nimport type { IUploadItem, TToast, TToastItem, TUploadItemStatus } from './types.js';\nimport {\n getUploadItemFilesDone,\n getUploadItemPercent,\n getUploadsSummary,\n type IUploadsSummary,\n} from './uploads.js';\n\n// Bundles the icons the toasts use, so they also show without a network (see toast-icons.ts)\nregisterToastIcons();\n\nconst CircularProgress = ({ progress, ...props }: { progress: number } & ComponentProps<'svg'>) => {\n const radius = 10;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference - (progress / 100) * circumference;\n\n return (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" {...props}>\n <circle\n cx=\"12\"\n cy=\"12\"\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeOpacity={0.15}\n strokeWidth=\"1.5\"\n />\n <circle\n cx=\"12\"\n cy=\"12\"\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n transform=\"rotate(-90 12 12)\"\n />\n\n <text\n x=\"12\"\n y=\"12\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fontSize=\"6\"\n fontWeight=\"500\"\n fill=\"currentColor\"\n >\n {progress}%\n </text>\n </svg>\n );\n};\n\nconst GREEN_RGB = 'var(--primary-green-rgb)';\nconst RED_RGB = 'var(--primary-red-rgb)';\n\nconst UPLOAD_ITEM_ICON: Record<TUploadItemStatus, { icon: string; rgb: string }> = {\n pending: { icon: 'solar:clock-circle-linear', rgb: 'var(--primary-rgb)' },\n uploading: { icon: 'beautinique:loading-spin', rgb: 'var(--primary-rgb)' },\n success: { icon: 'solar:check-circle-linear', rgb: GREEN_RGB },\n error: { icon: 'solar:danger-triangle-linear', rgb: RED_RGB },\n};\n\n/** The colour of an uploads toast follows how its uploads are doing. */\nconst uploadsRgb = ({ isSettled, failed }: IUploadsSummary) => {\n if (!isSettled) return 'var(--primary-rgb)';\n\n return failed > 0 ? RED_RGB : GREEN_RGB;\n};\n\nconst uploadsSummaryText = ({ filesDone, filesTotal, failed, isSettled }: IUploadsSummary) => {\n if (!isSettled) return `${String(filesDone)} of ${String(filesTotal)} uploaded`;\n if (failed === 0) return filesTotal === 1 ? 'Uploaded' : `All ${String(filesTotal)} uploaded`;\n\n return `${String(filesDone)} of ${String(filesTotal)} uploaded, ${String(failed)} failed`;\n};\n\n/** While uploading the title is the caller's (e.g. \"Please wait...\"); once over it says how it went. */\nconst uploadsHeading = (title: string, { failed, isSettled }: IUploadsSummary, uploads: number) => {\n if (!isSettled) return title;\n if (failed === 0) return 'Upload complete';\n\n return failed === uploads ? 'Upload failed' : 'Some uploads failed';\n};\n\nconst UploadRow = ({ item }: { item: IUploadItem }) => {\n const percent = getUploadItemPercent(item);\n const { icon, rgb } = UPLOAD_ITEM_ICON[item.status];\n\n return (\n <li data-status={item.status} className=\"flex items-center gap-1.5 md:gap-2\">\n <Icon\n icon={icon}\n className=\"size-3.5 shrink-0 md:size-4\"\n style={{ color: `rgb(${rgb})`, opacity: item.status === 'pending' ? 0.4 : 1 }}\n />\n\n <span className=\"text-primary w-20 shrink-0 truncate text-[9px] md:w-28 md:text-xs\">\n {item.label}\n </span>\n\n <div\n role=\"progressbar\"\n aria-label={`${item.label} upload`}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={percent}\n className=\"bg-primary/10 h-1 min-w-0 flex-1 overflow-hidden rounded-full\"\n >\n <div\n className=\"h-full rounded-full transition-[width] duration-300\"\n style={{ width: `${String(percent)}%`, backgroundColor: `rgb(${rgb})` }}\n />\n </div>\n\n <span className=\"text-tertiary w-8 shrink-0 text-right text-[9px] tabular-nums md:text-xs\">\n {getUploadItemFilesDone(item)}/{item.fileSizes.length}\n </span>\n </li>\n );\n};\n\ninterface IUploadsBodyProps {\n title: string;\n description?: string;\n items: IUploadItem[];\n summary: IUploadsSummary;\n rgb: string;\n}\n\nconst UploadsBody = ({ title, description, items, summary, rgb }: IUploadsBodyProps) => (\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\" aria-live=\"polite\">\n <div className=\"flex flex-col gap-0.5\">\n <p className=\"line-clamp-1 text-xs font-semibold md:text-sm\" style={{ color: `rgb(${rgb})` }}>\n {uploadsHeading(title, summary, items.length)}\n </p>\n\n {description && (\n <p className=\"text-tertiary line-clamp-1 text-[9px]/3 md:text-xs\">{description}</p>\n )}\n\n <p className=\"text-tertiary text-[9px]/3 tabular-nums md:text-xs\">\n {uploadsSummaryText(summary)}\n </p>\n </div>\n\n {items.length > 1 && (\n <ul className=\"flex flex-col gap-1\">\n {items.map((item) => (\n <UploadRow key={item.id} item={item} />\n ))}\n </ul>\n )}\n </div>\n);\n\nconst cardConfig = (type: TToast['type']) => {\n switch (type) {\n case TOAST_TYPE.success:\n return { iconName: 'solar:check-circle-linear', rgb: GREEN_RGB };\n case TOAST_TYPE.error:\n return { iconName: 'solar:danger-triangle-linear', rgb: RED_RGB };\n case TOAST_TYPE.warning:\n return { iconName: 'solar:danger-triangle-linear', rgb: 'var(--primary-yellow-rgb)' };\n case TOAST_TYPE.progress:\n case TOAST_TYPE.uploads:\n return { iconName: '', rgb: 'var(--primary-rgb)' };\n case TOAST_TYPE.loading:\n return { iconName: 'beautinique:loading-spin', rgb: 'var(--primary-rgb)' };\n case TOAST_TYPE.default:\n case TOAST_TYPE.custom:\n default:\n return { iconName: 'solar:info-circle-outline', rgb: 'var(--primary-rgb)' };\n }\n};\n\nconst ToasterItem = (props: TToastItem & IClassName) => {\n const {\n className = '',\n type,\n icon,\n buttonProps,\n isClosable = true,\n autoClose = true,\n closeTimer = 5000,\n } = props;\n\n const remove = useToastStore((s) => s.remove);\n\n const [visible, setVisible] = useState(false);\n const [mounted, setMounted] = useState(true);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // An uploads toast stays while anything is still uploading, then closes by itself (later when\n // something failed, so it can be read).\n const uploadsSummary = props.type === TOAST_TYPE.uploads ? getUploadsSummary(props.items) : null;\n const isUploadsSettled = uploadsSummary?.isSettled ?? false;\n\n let resolvedAutoClose = autoClose;\n let resolvedIsClosable = isClosable;\n let resolvedCloseTimer = closeTimer;\n\n if (TOAST_TYPE.loading === type || TOAST_TYPE.progress === type) {\n resolvedAutoClose = false;\n resolvedIsClosable = false;\n } else if (uploadsSummary) {\n resolvedAutoClose = isUploadsSettled;\n resolvedIsClosable = isUploadsSettled;\n resolvedCloseTimer = uploadsSummary.failed > 0 ? 8000 : 2500;\n }\n\n const config = uploadsSummary\n ? { iconName: '', rgb: uploadsRgb(uploadsSummary) }\n : cardConfig(type);\n\n const handleClose = useCallback(() => {\n setVisible(false);\n\n timeoutRef.current = setTimeout(() => {\n setMounted(false);\n remove(props.id);\n }, 300);\n }, [remove, props.id]);\n\n useEffect(() => {\n const enterTimer = setTimeout(() => {\n setVisible(true);\n }, 50);\n\n let autoTimer: ReturnType<typeof setTimeout> | null = null;\n\n if (resolvedAutoClose) {\n autoTimer = setTimeout(() => {\n handleClose();\n }, resolvedCloseTimer);\n }\n\n return () => {\n clearTimeout(enterTimer);\n if (autoTimer) clearTimeout(autoTimer);\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, [resolvedAutoClose, resolvedCloseTimer, handleClose]);\n\n if (!mounted) return null;\n\n const isCustom = type === TOAST_TYPE.custom;\n\n return (\n <div\n className={`rounded-xl border-2 transition-all duration-300 ease-in-out ${\n visible ? 'translate-x-0 opacity-100' : 'translate-x-full opacity-0'\n } ${className}`}\n style={{\n borderColor: `rgba(${config.rgb}, 0.2)`,\n boxShadow: `0 10px 10px 0px rgba(${config.rgb}, 0.1)`,\n }}\n >\n <div className=\"bg-secondary-invert flex w-full items-center gap-2 rounded-[10.25px] p-1.5 md:p-2.5 lg:p-3 [&>svg]:size-5 [&>svg]:shrink-0 [&>svg]:md:size-6 [&>svg]:lg:size-7\">\n {icon ??\n (props.type === TOAST_TYPE.progress ? (\n <CircularProgress\n progress={props.progress}\n style={{ strokeColor: `rgb(${config.rgb})` }}\n />\n ) : uploadsSummary ? (\n <CircularProgress\n progress={uploadsSummary.percent}\n style={{ color: `rgb(${config.rgb})` }}\n />\n ) : (\n <Icon icon={config.iconName} style={{ color: `rgb(${config.rgb})` }} />\n ))}\n\n {props.type === TOAST_TYPE.uploads && uploadsSummary ? (\n <UploadsBody\n title={props.title}\n description={props.description}\n items={props.items}\n summary={uploadsSummary}\n rgb={config.rgb}\n />\n ) : (\n <div className=\"flex flex-1 items-center justify-between gap-2\">\n <div className=\"flex flex-col gap-0.5\">\n {!isCustom && 'title' in props && (\n <p\n className=\"line-clamp-1 text-xs font-semibold md:text-sm\"\n style={{ color: `rgb(${config.rgb})` }}\n >\n {props.title}\n </p>\n )}\n\n {!isCustom && 'description' in props && (\n <p className=\"text-tertiary line-clamp-2 text-[9px]/3 whitespace-pre-line md:text-xs\">\n {props.description}\n </p>\n )}\n {isCustom && 'children' in props && props.children}\n </div>\n\n {buttonProps && type !== TOAST_TYPE.loading && type !== TOAST_TYPE.progress && (\n <Button\n {...buttonProps}\n content={buttonProps.content ?? 'Try Again'}\n pattern={buttonProps.pattern ?? 'secondary'}\n className={`w-fit! rounded-md! px-2! py-1! pt-1.5! text-[10px] whitespace-nowrap md:text-xs! ${buttonProps.className ?? ''}`}\n />\n )}\n </div>\n )}\n\n {resolvedIsClosable && (\n <Icon\n icon=\"lucide:x\"\n className=\"text-primary cursor-pointer md:size-5\"\n onClick={handleClose}\n />\n )}\n </div>\n </div>\n );\n};\n\n/*\n * The store changes only the toast that was updated (the others keep the same object), and a toast\n * that is uploading is updated many times a second. With `memo` the toasts that did not change\n * are not rendered again for each of those updates.\n */\nexport const Toaster = memo(ToasterItem);\n\nexport const ToastContainer = () => {\n const toasts = useToastStore((s) => s.toasts);\n\n if (toasts.length === 0) return null;\n\n return (\n <div className=\"base:max-w-sm fixed right-2 bottom-2 z-999 flex w-full max-w-xs flex-col gap-2 sm:max-w-md md:right-4 md:bottom-4 md:max-w-lg lg:right-8 lg:bottom-8 lg:max-w-xl\">\n {toasts.map((toast) => (\n <Toaster key={toast.id} {...toast} id={toast.id} />\n ))}\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/constants.ts","../../src/toast/toast.store.ts","../../src/toast/toast-icons.ts","../../src/lib/button.ts","../../src/ui/Button.tsx","../../src/toast/toaster.ts","../../src/toast/uploads.ts","../../src/toast/ToastContainer.tsx"],"names":["create","nanoid","addCollection","jsxs","jsx","Icon","remove","useState","useRef","useCallback","useEffect","memo"],"mappings":"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","file":"index.cjs","sourcesContent":["export const TOOLTIP_GAP = 15 as const;\nexport const TOOLTIP_ANIMATION_DURATION = 400 as const;\n/** The least space a tooltip keeps between itself and the edge of the window. */\nexport const TOOLTIP_VIEWPORT_MARGIN = 8 as const;\n/** The arrow stays at least this far from the ends of the tooltip (its own size and the rounded corner). */\nexport const TOOLTIP_ARROW_INSET = 16 as const;\n\nexport const TOAST_TYPES = [\n 'success',\n 'error',\n 'warning',\n 'progress',\n 'uploads',\n 'loading',\n 'default',\n 'custom',\n] as const;\n\nexport const TOAST_TYPE = Object.fromEntries(TOAST_TYPES.map((type) => [type, type])) as {\n [K in (typeof TOAST_TYPES)[number]]: K;\n};\n","import { nanoid } from 'nanoid';\nimport { create } from 'zustand';\n\nimport { TOAST_TYPE } from '../lib/constants.js';\nimport type { IToastStore } from './types.js';\n\nconst useToastStore = create<IToastStore>((set) => ({\n toasts: [],\n\n add: (toast) => {\n const id = nanoid();\n\n set((state) => ({ toasts: [...state.toasts, { ...toast, id }] }));\n\n return id; // return the id of the toast for removal\n },\n\n update: {\n progress: (id, progress) => {\n set((state) => ({\n toasts: state.toasts.map((toast) => (toast.id === id ? { ...toast, progress } : toast)),\n }));\n },\n\n uploadItem: (id, itemId, patch) => {\n set((state) => ({\n toasts: state.toasts.map((toast) =>\n toast.id === id && toast.type === TOAST_TYPE.uploads\n ? {\n ...toast,\n items: toast.items.map((item) =>\n item.id === itemId ? { ...item, ...patch } : item,\n ),\n }\n : toast,\n ),\n }));\n },\n },\n\n remove: (id) => {\n set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));\n },\n}));\n\nexport { useToastStore };\n","import { addCollection, type IconifyJSON } from '@iconify/react';\n\n/*\n * Iconify downloads an icon's SVG from its API the first time the icon is shown, and keeps it in\n * memory. A toast's icon is very often needed for the first time exactly when the download cannot\n * work: the \"You're offline\" toast, or the error toast of a request that failed because there is no\n * internet. Those icons are bundled here, so every toast has its icon without a network.\n *\n * Add an icon here when a toast starts using one (see `cardConfig` in `components/ui/Toaster.tsx`).\n * The data is what `https://api.iconify.design/<prefix>.json?icons=<name>` answers.\n */\nconst TOAST_ICON_SETS: IconifyJSON[] = [\n {\n prefix: 'solar',\n width: 24,\n height: 24,\n icons: {\n // warning and error toasts\n 'danger-triangle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><path d=\"M5.31171 10.7615C8.23007 5.58716 9.68925 3 12 3C14.3107 3 15.7699 5.58716 18.6883 10.7615L19.0519 11.4063C21.4771 15.7061 22.6897 17.856 21.5937 19.428C20.4978 21 17.7864 21 12.3637 21H11.6363C6.21356 21 3.50217 21 2.40626 19.428C1.31034 17.856 2.52291 15.7061 4.94805 11.4063L5.31171 10.7615Z\"/><path d=\"M12 8V13\"/><path stroke-linejoin=\"round\" d=\"M12 16H12.0001\"/></g>',\n },\n // success toast\n 'check-circle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path stroke-linejoin=\"round\" d=\"M8.5 12.5L10.5 14.5L15.5 9.5\"/></g>',\n },\n // an upload that is waiting its turn, in an uploads toast\n 'clock-circle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path stroke-linejoin=\"round\" d=\"M12 8V12L14.5 14.5\"/></g>',\n },\n // default and custom toasts\n 'info-circle-outline': {\n body: '<g fill=\"currentColor\"><path d=\"M12 17.75C12.4142 17.75 12.75 17.4142 12.75 17V11C12.75 10.5858 12.4142 10.25 12 10.25C11.5858 10.25 11.25 10.5858 11.25 11V17C11.25 17.4142 11.5858 17.75 12 17.75Z\"/><path d=\"M12 7C12.5523 7 13 7.44772 13 8C13 8.55228 12.5523 9 12 9C11.4477 9 11 8.55228 11 8C11 7.44772 11.4477 7 12 7Z\"/><path fill-rule=\"evenodd\" d=\"M1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12ZM12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.9371 2.75 12 2.75Z\" clip-rule=\"evenodd\"/></g>',\n },\n },\n },\n {\n prefix: 'beautinique',\n width: 24,\n height: 24,\n icons: {\n /*\n * The spinner of the loading toast and of an upload that is going on. It turns itself, inside\n * the svg (`animateTransform`, around the centre of the ring), instead of being turned by a\n * css `animate-spin` on the svg: the browser then draws the ring again at the exact angle on\n * every frame. A css turn rotates a picture of the whole svg, and on a screen with a scaling of\n * 125% an icon of 20px is 25 device pixels, so the middle of that picture is half a pixel off\n * and the ring jumps up and down a little while it turns. Do not add `animate-spin` to it.\n */\n 'loading-spin': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M17 3.34A10 10 0 1 0 22 12\"><animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\"/></path>',\n },\n },\n },\n {\n prefix: 'lucide',\n width: 24,\n height: 24,\n icons: {\n // the close button of a closable toast\n x: {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M18 6L6 18M6 6l12 12\"/>',\n },\n },\n },\n];\n\n/**\n * Registers the icons above with Iconify (calling it again is harmless). It is a function that\n * `ToastContainer` calls, and not something that happens when this file is imported, on purpose: a\n * bare `import './toast-icons.js'` is dropped by the bundler when the package's `sideEffects` field\n * does not list the file (the build says \"ignored-bare-import\"), and then the icons are missing.\n */\nexport const registerToastIcons = () => {\n for (const iconSet of TOAST_ICON_SETS) addCollection(iconSet);\n};\n\n/** Every icon name registered above, e.g. `solar:danger-triangle-linear`. */\nexport const TOAST_ICON_NAMES = TOAST_ICON_SETS.flatMap(({ prefix, icons }) =>\n Object.keys(icons).map((name) => `${prefix}:${name}`),\n);\n","import type { IButton } from '../types/component.js';\n\ntype TPattern = IButton['pattern'];\n\n// A `Record`: adding a pattern to the type is a type error here until it has a look.\nconst PATTERN_CSS: Record<TPattern, string> = {\n primary: 'text-white bg-sky-blue-burst shadow-primary-btn hover:shadow-primary-btn-hover',\n secondary:\n 'text-secondary-invert bg-secondary shadow-secondary-btn hover:shadow-secondary-btn-hover',\n tertiary: 'text-tertiary-invert bg-tertiary shadow-tertiary-btn hover:shadow-tertiary-btn-hover',\n outline: 'text-primary border border-primary shadow-outline-btn hover:shadow-outline-btn-hover',\n transparent: 'bg-transparent border border-primary/30 text-secondary',\n};\n\n/** The look of a pattern; a pattern nobody knows (from code that is not type checked) is transparent. */\nexport const getButtonCss = (pattern: TPattern) =>\n Object.hasOwn(PATTERN_CSS, pattern) ? PATTERN_CSS[pattern] : PATTERN_CSS.transparent;\n","import { Icon } from '@iconify/react';\n\nimport { getButtonCss } from '../lib/button.js';\nimport type { IButton } from '../types/component.js';\n\nconst BASE_CSS =\n 'group flex w-full cursor-pointer items-center justify-center gap-1 rounded-lg px-4 py-3 text-sm leading-4 transition-all duration-300 disabled:cursor-not-allowed disabled:opacity-85 lg:px-5 lg:py-4 xl:text-base';\n\nexport const Button = ({\n pattern,\n content,\n className = '',\n leftIcon,\n rightIcon,\n buttonProps,\n ref,\n}: IButton) => (\n // The classes that are given come last but do not remove the button's own: to win over one of\n // them give it with `!` (`rounded-md!`), the way the toast's button does.\n <button\n {...buttonProps}\n ref={ref}\n className={`${BASE_CSS} ${getButtonCss(pattern)} ${className} ${buttonProps?.className ?? ''}`}\n type={buttonProps?.type ?? 'button'}\n >\n {leftIcon && <Icon {...leftIcon} />}\n {typeof content === 'object' ? <Icon {...content} /> : content}\n {rightIcon && <Icon {...rightIcon} />}\n </button>\n);\n","import { TOAST_TYPE } from '../lib/constants.js';\nimport { useToastStore } from './toast.store.js';\nimport type {\n ICustomToast,\n IDefaultToast,\n ILoadingToast,\n IProgressToast,\n IUploadItem,\n IUploadsToast,\n TProgressToastOptions,\n} from './types.js';\n\nconst { add, update, remove } = useToastStore.getState();\nexport const toaster = {\n success: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.success }),\n error: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.error }),\n warning: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.warning }),\n default: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.default }),\n loading: (data: Omit<ILoadingToast, 'type'>) => add({ ...data, type: TOAST_TYPE.loading }),\n custom: (data: ICustomToast) => add(data),\n progress: {\n start: (data: Omit<IProgressToast, 'type'>) => add({ ...data, type: TOAST_TYPE.progress }),\n update: (toastId: string, progress: number) => {\n update.progress(toastId, progress);\n },\n end: (toastId: string) => {\n remove(toastId);\n },\n },\n uploads: {\n start: (data: Omit<IUploadsToast, 'type'>) => add({ ...data, type: TOAST_TYPE.uploads }),\n update: (toastId: string, itemId: string, patch: Partial<Omit<IUploadItem, 'id'>>) => {\n update.uploadItem(toastId, itemId, patch);\n },\n },\n remove: (toastId: string) => {\n remove(toastId);\n },\n};\n\nexport const withProgressToast = async <T>({\n title,\n description,\n request,\n}: TProgressToastOptions<T>): Promise<T> => {\n const toastId = toaster.progress.start({ title, description, progress: 0 });\n\n try {\n const response = await request((event) => {\n if (!event.total) return;\n\n toaster.progress.update(toastId, Math.round((event.loaded * 100) / event.total));\n });\n\n toaster.progress.update(toastId, 100);\n\n return response;\n } finally {\n toaster.progress.end(toastId);\n }\n};\n","import { toaster } from './toaster.js';\nimport type {\n IUploadGroup,\n IUploadItem,\n IUploadItemHandle,\n TUploadItemStatus,\n TUploadProgressHandler,\n} from './types.js';\n\nconst sum = (numbers: number[]) => numbers.reduce((total, value) => total + value, 0);\n\n/* ===================== WHAT THE TOAST SHOWS ===================== */\n\nexport const isUploadItemSettled = ({ status }: Pick<IUploadItem, 'status'>) =>\n status === 'success' || status === 'error';\n\n/**\n * How many files of an upload are through. An upload is one request, so a file is known to be\n * through only once the server has answered; until then the files that were completely sent count,\n * except the last one (it may still be on its way to the storage). A failed upload has none.\n */\nexport const getUploadItemFilesDone = ({\n status,\n loaded,\n fileSizes,\n}: Pick<IUploadItem, 'status' | 'loaded' | 'fileSizes'>) => {\n if (status === 'success') return fileSizes.length;\n if (status !== 'uploading') return 0;\n\n let sent = 0;\n let bytes = 0;\n\n for (const size of fileSizes) {\n bytes += size;\n\n if (bytes > loaded) break;\n\n sent += 1;\n }\n\n return Math.min(sent, Math.max(fileSizes.length - 1, 0));\n};\n\n/** How far one upload is, 0 to 100. 100 is only for an upload the server has answered. */\nexport const getUploadItemPercent = ({\n status,\n loaded,\n total,\n}: Pick<IUploadItem, 'status' | 'loaded' | 'total'>) => {\n if (status === 'success') return 100;\n if (status === 'pending' || total <= 0) return 0;\n\n return Math.min(99, Math.round((Math.min(loaded, total) * 100) / total));\n};\n\nexport interface IUploadsSummary {\n /** Overall progress by bytes, 0 to 100. 100 only when every upload has succeeded. */\n percent: number;\n filesDone: number;\n filesTotal: number;\n /** How many uploads failed. */\n failed: number;\n /** Every upload has either succeeded or failed. */\n isSettled: boolean;\n}\n\nexport const getUploadsSummary = (items: IUploadItem[]): IUploadsSummary => {\n const failed = items.filter(({ status }) => status === 'error').length;\n const isSettled = items.every(isUploadItemSettled);\n const bytesTotal = sum(items.map(({ total }) => total));\n const bytesDone = sum(\n items.map((item) =>\n item.status === 'success' ? item.total : Math.min(item.loaded, item.total),\n ),\n );\n\n let percent = bytesTotal > 0 ? Math.round((bytesDone * 100) / bytesTotal) : 0;\n\n if (isSettled && failed === 0) percent = 100;\n else percent = Math.min(percent, 99);\n\n return {\n percent,\n filesDone: sum(items.map(getUploadItemFilesDone)),\n filesTotal: sum(items.map(({ fileSizes }) => fileSizes.length)),\n failed,\n isSettled,\n };\n};\n\n/* ===================== FILES ===================== */\n\n/** The files of a FormData, in the order they are sent. */\nexport const getFormDataFiles = (data: FormData, key = 'files'): File[] =>\n data.getAll(key).filter((value): value is File => value instanceof File);\n\n/* ===================== THE TOAST OF A GROUP OF UPLOADS ===================== */\n\ninterface IUploadGroupOptions {\n title: string;\n description?: string;\n items: { id: string; label: string; files: File[] }[];\n}\n\n/**\n * Opens one toast for the uploads of `items`. It closes by itself a moment after every upload is\n * over. Returns nothing when there is nothing to upload, so no empty toast is shown.\n */\nexport const createUploadsToast = ({\n title,\n description,\n items,\n}: IUploadGroupOptions): IUploadGroup | undefined => {\n if (items.length === 0) return undefined;\n\n const statuses = new Map<string, TUploadItemStatus>(items.map(({ id }) => [id, 'pending']));\n\n const toastId = toaster.uploads.start({\n title,\n description,\n items: items.map(({ id, label, files }) => {\n const fileSizes = files.map(({ size }) => size);\n\n return { id, label, status: 'pending', loaded: 0, total: sum(fileSizes), fileSizes };\n }),\n });\n\n const patch = (id: string, changes: Partial<Omit<IUploadItem, 'id'>>) => {\n if (changes.status) statuses.set(id, changes.status);\n\n toaster.uploads.update(toastId, id, changes);\n };\n\n return {\n item: (id) => ({\n run: async (request) => {\n patch(id, { status: 'uploading' });\n\n try {\n const result = await request((event) => {\n // The browser says nothing about the total for some requests: keep the size estimate then.\n if (!event.total) return;\n\n patch(id, { loaded: event.loaded, total: event.total });\n });\n\n patch(id, { status: 'success' });\n\n return result;\n } catch (error) {\n patch(id, { status: 'error' });\n\n throw error;\n }\n },\n }),\n\n end: () => {\n for (const [id, status] of statuses) {\n if (status === 'pending' || status === 'uploading') patch(id, { status: 'error' });\n }\n },\n };\n};\n\n/** The toast for a single request that uploads several files at once. */\nexport const withUploadsToast = async <T>({\n title,\n description,\n files,\n request,\n}: {\n title: string;\n description?: string;\n files: File[];\n request: (onProgress: TUploadProgressHandler) => Promise<T>;\n}): Promise<T> => {\n const group = createUploadsToast({\n title,\n description,\n items: files.length > 0 ? [{ id: 'files', label: description ?? title, files }] : [],\n });\n\n if (!group) return request(() => undefined);\n\n try {\n return await group.item('files').run(request);\n } finally {\n group.end();\n }\n};\n\n/**\n * Runs the uploads of several fields (e.g. the images of each editor of a form step) behind one\n * toast with a row for every field that has files. `run` is called for every field, with the row of\n * that field to give to its upload (nothing when the toast has no row for it). Every upload is\n * waited for, so none is shown as failed just because another one failed; if any failed, the first\n * error is thrown once all are over.\n */\nexport const runUploadsInToast = async <TId extends string, TResult>({\n title,\n description,\n uploads,\n run,\n}: {\n title: string;\n description?: string;\n uploads: { id: TId; label: string; files: File[] }[];\n run: (id: TId, progress: IUploadItemHandle | undefined) => Promise<TResult>;\n}): Promise<Record<TId, TResult>> => {\n const group = createUploadsToast({\n title,\n description,\n items: uploads.filter(({ files }) => files.length > 0),\n });\n\n const settled = await Promise.allSettled(uploads.map(({ id }) => run(id, group?.item(id))));\n\n group?.end();\n\n const results = {} as Record<TId, TResult>;\n\n settled.forEach((result, index) => {\n if (result.status === 'fulfilled') results[uploads[index].id] = result.value;\n });\n\n const failure = settled.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n );\n\n if (failure) {\n throw failure.reason instanceof Error ? failure.reason : new Error('Upload failed');\n }\n\n return results;\n};\n","import { Icon } from '@iconify/react';\nimport { type ComponentProps, memo, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { TOAST_TYPE } from '../lib/constants.js';\nimport type { IClassName } from '../types/component.js';\nimport { Button } from '../ui/Button.js';\nimport { registerToastIcons } from './toast-icons.js';\nimport { useToastStore } from './toast.store.js';\nimport type { IUploadItem, TToast, TToastItem, TUploadItemStatus } from './types.js';\nimport {\n getUploadItemFilesDone,\n getUploadItemPercent,\n getUploadsSummary,\n type IUploadsSummary,\n} from './uploads.js';\n\n// Bundles the icons the toasts use, so they also show without a network (see toast-icons.ts)\nregisterToastIcons();\n\nconst CircularProgress = ({ progress, ...props }: { progress: number } & ComponentProps<'svg'>) => {\n const radius = 10;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference - (progress / 100) * circumference;\n\n return (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" {...props}>\n <circle\n cx=\"12\"\n cy=\"12\"\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeOpacity={0.15}\n strokeWidth=\"1.5\"\n />\n <circle\n cx=\"12\"\n cy=\"12\"\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n transform=\"rotate(-90 12 12)\"\n />\n\n <text\n x=\"12\"\n y=\"12\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fontSize=\"6\"\n fontWeight=\"500\"\n fill=\"currentColor\"\n >\n {progress}%\n </text>\n </svg>\n );\n};\n\nconst GREEN_RGB = 'var(--primary-green-rgb)';\nconst RED_RGB = 'var(--primary-red-rgb)';\n\nconst UPLOAD_ITEM_ICON: Record<TUploadItemStatus, { icon: string; rgb: string }> = {\n pending: { icon: 'solar:clock-circle-linear', rgb: 'var(--primary-rgb)' },\n uploading: { icon: 'beautinique:loading-spin', rgb: 'var(--primary-rgb)' },\n success: { icon: 'solar:check-circle-linear', rgb: GREEN_RGB },\n error: { icon: 'solar:danger-triangle-linear', rgb: RED_RGB },\n};\n\n/** The colour of an uploads toast follows how its uploads are doing. */\nconst uploadsRgb = ({ isSettled, failed }: IUploadsSummary) => {\n if (!isSettled) return 'var(--primary-rgb)';\n\n return failed > 0 ? RED_RGB : GREEN_RGB;\n};\n\nconst uploadsSummaryText = ({ filesDone, filesTotal, failed, isSettled }: IUploadsSummary) => {\n if (!isSettled) return `${String(filesDone)} of ${String(filesTotal)} uploaded`;\n if (failed === 0) return filesTotal === 1 ? 'Uploaded' : `All ${String(filesTotal)} uploaded`;\n\n return `${String(filesDone)} of ${String(filesTotal)} uploaded, ${String(failed)} failed`;\n};\n\n/** While uploading the title is the caller's (e.g. \"Please wait...\"); once over it says how it went. */\nconst uploadsHeading = (title: string, { failed, isSettled }: IUploadsSummary, uploads: number) => {\n if (!isSettled) return title;\n if (failed === 0) return 'Upload complete';\n\n return failed === uploads ? 'Upload failed' : 'Some uploads failed';\n};\n\nconst UploadRow = ({ item }: { item: IUploadItem }) => {\n const percent = getUploadItemPercent(item);\n const { icon, rgb } = UPLOAD_ITEM_ICON[item.status];\n\n return (\n <li data-status={item.status} className=\"flex items-center gap-1.5 md:gap-2\">\n <Icon\n icon={icon}\n className=\"size-3.5 shrink-0 md:size-4\"\n style={{ color: `rgb(${rgb})`, opacity: item.status === 'pending' ? 0.4 : 1 }}\n />\n\n <span className=\"text-primary w-20 shrink-0 truncate text-[9px] md:w-28 md:text-xs\">\n {item.label}\n </span>\n\n <div\n role=\"progressbar\"\n aria-label={`${item.label} upload`}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={percent}\n className=\"bg-primary/10 h-1 min-w-0 flex-1 overflow-hidden rounded-full\"\n >\n <div\n className=\"h-full rounded-full transition-[width] duration-300\"\n style={{ width: `${String(percent)}%`, backgroundColor: `rgb(${rgb})` }}\n />\n </div>\n\n <span className=\"text-tertiary w-8 shrink-0 text-right text-[9px] tabular-nums md:text-xs\">\n {getUploadItemFilesDone(item)}/{item.fileSizes.length}\n </span>\n </li>\n );\n};\n\ninterface IUploadsBodyProps {\n title: string;\n description?: string;\n items: IUploadItem[];\n summary: IUploadsSummary;\n rgb: string;\n}\n\nconst UploadsBody = ({ title, description, items, summary, rgb }: IUploadsBodyProps) => (\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\" aria-live=\"polite\">\n <div className=\"flex flex-col gap-0.5\">\n <p className=\"line-clamp-1 text-xs font-semibold md:text-sm\" style={{ color: `rgb(${rgb})` }}>\n {uploadsHeading(title, summary, items.length)}\n </p>\n\n {description && (\n <p className=\"text-tertiary line-clamp-1 text-[9px]/3 md:text-xs\">{description}</p>\n )}\n\n <p className=\"text-tertiary text-[9px]/3 tabular-nums md:text-xs\">\n {uploadsSummaryText(summary)}\n </p>\n </div>\n\n {items.length > 1 && (\n <ul className=\"flex flex-col gap-1\">\n {items.map((item) => (\n <UploadRow key={item.id} item={item} />\n ))}\n </ul>\n )}\n </div>\n);\n\nconst cardConfig = (type: TToast['type']) => {\n switch (type) {\n case TOAST_TYPE.success:\n return { iconName: 'solar:check-circle-linear', rgb: GREEN_RGB };\n case TOAST_TYPE.error:\n return { iconName: 'solar:danger-triangle-linear', rgb: RED_RGB };\n case TOAST_TYPE.warning:\n return { iconName: 'solar:danger-triangle-linear', rgb: 'var(--primary-yellow-rgb)' };\n case TOAST_TYPE.progress:\n case TOAST_TYPE.uploads:\n return { iconName: '', rgb: 'var(--primary-rgb)' };\n case TOAST_TYPE.loading:\n return { iconName: 'beautinique:loading-spin', rgb: 'var(--primary-rgb)' };\n case TOAST_TYPE.default:\n case TOAST_TYPE.custom:\n default:\n return { iconName: 'solar:info-circle-outline', rgb: 'var(--primary-rgb)' };\n }\n};\n\nconst ToasterItem = (props: TToastItem & IClassName) => {\n const {\n className = '',\n type,\n icon,\n buttonProps,\n isClosable = true,\n autoClose = true,\n closeTimer = 5000,\n } = props;\n\n const remove = useToastStore((s) => s.remove);\n\n const [visible, setVisible] = useState(false);\n const [mounted, setMounted] = useState(true);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // An uploads toast stays while anything is still uploading, then closes by itself (later when\n // something failed, so it can be read).\n const uploadsSummary = props.type === TOAST_TYPE.uploads ? getUploadsSummary(props.items) : null;\n const isUploadsSettled = uploadsSummary?.isSettled ?? false;\n\n let resolvedAutoClose = autoClose;\n let resolvedIsClosable = isClosable;\n let resolvedCloseTimer = closeTimer;\n\n if (TOAST_TYPE.loading === type || TOAST_TYPE.progress === type) {\n resolvedAutoClose = false;\n resolvedIsClosable = false;\n } else if (uploadsSummary) {\n resolvedAutoClose = isUploadsSettled;\n resolvedIsClosable = isUploadsSettled;\n resolvedCloseTimer = uploadsSummary.failed > 0 ? 8000 : 2500;\n }\n\n const config = uploadsSummary\n ? { iconName: '', rgb: uploadsRgb(uploadsSummary) }\n : cardConfig(type);\n\n const handleClose = useCallback(() => {\n setVisible(false);\n\n timeoutRef.current = setTimeout(() => {\n setMounted(false);\n remove(props.id);\n }, 300);\n }, [remove, props.id]);\n\n useEffect(() => {\n const enterTimer = setTimeout(() => {\n setVisible(true);\n }, 50);\n\n let autoTimer: ReturnType<typeof setTimeout> | null = null;\n\n if (resolvedAutoClose) {\n autoTimer = setTimeout(() => {\n handleClose();\n }, resolvedCloseTimer);\n }\n\n return () => {\n clearTimeout(enterTimer);\n if (autoTimer) clearTimeout(autoTimer);\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, [resolvedAutoClose, resolvedCloseTimer, handleClose]);\n\n if (!mounted) return null;\n\n const isCustom = type === TOAST_TYPE.custom;\n\n return (\n <div\n className={`rounded-xl border-2 transition-all duration-300 ease-in-out ${\n visible ? 'translate-x-0 opacity-100' : 'translate-x-full opacity-0'\n } ${className}`}\n style={{\n borderColor: `rgba(${config.rgb}, 0.2)`,\n boxShadow: `0 10px 10px 0px rgba(${config.rgb}, 0.1)`,\n }}\n >\n <div className=\"bg-secondary-invert flex w-full items-center gap-2 rounded-[10.25px] p-1.5 md:p-2.5 lg:p-3 [&>svg]:size-5 [&>svg]:shrink-0 [&>svg]:md:size-6 [&>svg]:lg:size-7\">\n {icon ??\n (props.type === TOAST_TYPE.progress ? (\n <CircularProgress\n progress={props.progress}\n style={{ strokeColor: `rgb(${config.rgb})` }}\n />\n ) : uploadsSummary ? (\n <CircularProgress\n progress={uploadsSummary.percent}\n style={{ color: `rgb(${config.rgb})` }}\n />\n ) : (\n <Icon icon={config.iconName} style={{ color: `rgb(${config.rgb})` }} />\n ))}\n\n {props.type === TOAST_TYPE.uploads && uploadsSummary ? (\n <UploadsBody\n title={props.title}\n description={props.description}\n items={props.items}\n summary={uploadsSummary}\n rgb={config.rgb}\n />\n ) : (\n <div className=\"flex flex-1 items-center justify-between gap-2\">\n <div className=\"flex flex-col gap-0.5\">\n {!isCustom && 'title' in props && (\n <p\n className=\"line-clamp-1 text-xs font-semibold md:text-sm\"\n style={{ color: `rgb(${config.rgb})` }}\n >\n {props.title}\n </p>\n )}\n\n {!isCustom && 'description' in props && (\n <p className=\"text-tertiary line-clamp-2 text-[9px]/3 whitespace-pre-line md:text-xs\">\n {props.description}\n </p>\n )}\n {isCustom && 'children' in props && props.children}\n </div>\n\n {buttonProps && type !== TOAST_TYPE.loading && type !== TOAST_TYPE.progress && (\n <Button\n {...buttonProps}\n content={buttonProps.content ?? 'Try Again'}\n pattern={buttonProps.pattern ?? 'secondary'}\n className={`w-fit! rounded-md! px-2! py-1! pt-1.5! text-[10px] whitespace-nowrap md:text-xs! ${buttonProps.className ?? ''}`}\n />\n )}\n </div>\n )}\n\n {resolvedIsClosable && (\n <Icon\n icon=\"lucide:x\"\n className=\"text-primary cursor-pointer md:size-5\"\n onClick={handleClose}\n />\n )}\n </div>\n </div>\n );\n};\n\n/*\n * The store changes only the toast that was updated (the others keep the same object), and a toast\n * that is uploading is updated many times a second. With `memo` the toasts that did not change\n * are not rendered again for each of those updates.\n */\nexport const Toaster = memo(ToasterItem);\n\nexport const ToastContainer = () => {\n const toasts = useToastStore((s) => s.toasts);\n\n if (toasts.length === 0) return null;\n\n return (\n <div className=\"base:max-w-sm fixed right-2 bottom-2 z-999 flex w-full max-w-xs flex-col gap-2 sm:max-w-md md:right-4 md:bottom-4 md:max-w-lg lg:right-8 lg:bottom-8 lg:max-w-xl\">\n {toasts.map((toast) => (\n <Toaster key={toast.id} {...toast} id={toast.id} />\n ))}\n </div>\n );\n};\n"]}
|
package/dist/toast/index.js
CHANGED
|
@@ -2,7 +2,6 @@ import { nanoid } from 'nanoid';
|
|
|
2
2
|
import { create } from 'zustand';
|
|
3
3
|
import { addCollection, Icon } from '@iconify/react';
|
|
4
4
|
import { memo, useState, useRef, useCallback, useEffect } from 'react';
|
|
5
|
-
import { twMerge } from 'tailwind-merge';
|
|
6
5
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
6
|
|
|
8
7
|
var __defProp = Object.defineProperty;
|
|
@@ -132,14 +131,14 @@ var Button = /* @__PURE__ */ __name(({
|
|
|
132
131
|
buttonProps,
|
|
133
132
|
ref
|
|
134
133
|
}) => (
|
|
135
|
-
//
|
|
136
|
-
//
|
|
134
|
+
// The classes that are given come last but do not remove the button's own: to win over one of
|
|
135
|
+
// them give it with `!` (`rounded-md!`), the way the toast's button does.
|
|
137
136
|
/* @__PURE__ */ jsxs(
|
|
138
137
|
"button",
|
|
139
138
|
{
|
|
140
139
|
...buttonProps,
|
|
141
140
|
ref,
|
|
142
|
-
className:
|
|
141
|
+
className: `${BASE_CSS} ${getButtonCss(pattern)} ${className} ${buttonProps?.className ?? ""}`,
|
|
143
142
|
type: buttonProps?.type ?? "button",
|
|
144
143
|
children: [
|
|
145
144
|
leftIcon && /* @__PURE__ */ jsx(Icon, { ...leftIcon }),
|
package/dist/toast/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/constants.ts","../../src/toast/toast.store.ts","../../src/toast/toast-icons.ts","../../src/lib/button.ts","../../src/ui/Button.tsx","../../src/toast/toaster.ts","../../src/toast/uploads.ts","../../src/toast/ToastContainer.tsx"],"names":["jsxs","jsx","Icon","remove"],"mappings":"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","file":"index.js","sourcesContent":["export const TOOLTIP_GAP = 15 as const;\nexport const TOOLTIP_ANIMATION_DURATION = 400 as const;\n/** The least space a tooltip keeps between itself and the edge of the window. */\nexport const TOOLTIP_VIEWPORT_MARGIN = 8 as const;\n/** The arrow stays at least this far from the ends of the tooltip (its own size and the rounded corner). */\nexport const TOOLTIP_ARROW_INSET = 16 as const;\n\nexport const TOAST_TYPES = [\n 'success',\n 'error',\n 'warning',\n 'progress',\n 'uploads',\n 'loading',\n 'default',\n 'custom',\n] as const;\n\nexport const TOAST_TYPE = Object.fromEntries(TOAST_TYPES.map((type) => [type, type])) as {\n [K in (typeof TOAST_TYPES)[number]]: K;\n};\n","import { nanoid } from 'nanoid';\nimport { create } from 'zustand';\n\nimport { TOAST_TYPE } from '../lib/constants.js';\nimport type { IToastStore } from './types.js';\n\nconst useToastStore = create<IToastStore>((set) => ({\n toasts: [],\n\n add: (toast) => {\n const id = nanoid();\n\n set((state) => ({ toasts: [...state.toasts, { ...toast, id }] }));\n\n return id; // return the id of the toast for removal\n },\n\n update: {\n progress: (id, progress) => {\n set((state) => ({\n toasts: state.toasts.map((toast) => (toast.id === id ? { ...toast, progress } : toast)),\n }));\n },\n\n uploadItem: (id, itemId, patch) => {\n set((state) => ({\n toasts: state.toasts.map((toast) =>\n toast.id === id && toast.type === TOAST_TYPE.uploads\n ? {\n ...toast,\n items: toast.items.map((item) =>\n item.id === itemId ? { ...item, ...patch } : item,\n ),\n }\n : toast,\n ),\n }));\n },\n },\n\n remove: (id) => {\n set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));\n },\n}));\n\nexport { useToastStore };\n","import { addCollection, type IconifyJSON } from '@iconify/react';\n\n/*\n * Iconify downloads an icon's SVG from its API the first time the icon is shown, and keeps it in\n * memory. A toast's icon is very often needed for the first time exactly when the download cannot\n * work: the \"You're offline\" toast, or the error toast of a request that failed because there is no\n * internet. Those icons are bundled here, so every toast has its icon without a network.\n *\n * Add an icon here when a toast starts using one (see `cardConfig` in `components/ui/Toaster.tsx`).\n * The data is what `https://api.iconify.design/<prefix>.json?icons=<name>` answers.\n */\nconst TOAST_ICON_SETS: IconifyJSON[] = [\n {\n prefix: 'solar',\n width: 24,\n height: 24,\n icons: {\n // warning and error toasts\n 'danger-triangle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><path d=\"M5.31171 10.7615C8.23007 5.58716 9.68925 3 12 3C14.3107 3 15.7699 5.58716 18.6883 10.7615L19.0519 11.4063C21.4771 15.7061 22.6897 17.856 21.5937 19.428C20.4978 21 17.7864 21 12.3637 21H11.6363C6.21356 21 3.50217 21 2.40626 19.428C1.31034 17.856 2.52291 15.7061 4.94805 11.4063L5.31171 10.7615Z\"/><path d=\"M12 8V13\"/><path stroke-linejoin=\"round\" d=\"M12 16H12.0001\"/></g>',\n },\n // success toast\n 'check-circle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path stroke-linejoin=\"round\" d=\"M8.5 12.5L10.5 14.5L15.5 9.5\"/></g>',\n },\n // an upload that is waiting its turn, in an uploads toast\n 'clock-circle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path stroke-linejoin=\"round\" d=\"M12 8V12L14.5 14.5\"/></g>',\n },\n // default and custom toasts\n 'info-circle-outline': {\n body: '<g fill=\"currentColor\"><path d=\"M12 17.75C12.4142 17.75 12.75 17.4142 12.75 17V11C12.75 10.5858 12.4142 10.25 12 10.25C11.5858 10.25 11.25 10.5858 11.25 11V17C11.25 17.4142 11.5858 17.75 12 17.75Z\"/><path d=\"M12 7C12.5523 7 13 7.44772 13 8C13 8.55228 12.5523 9 12 9C11.4477 9 11 8.55228 11 8C11 7.44772 11.4477 7 12 7Z\"/><path fill-rule=\"evenodd\" d=\"M1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12ZM12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.9371 2.75 12 2.75Z\" clip-rule=\"evenodd\"/></g>',\n },\n },\n },\n {\n prefix: 'beautinique',\n width: 24,\n height: 24,\n icons: {\n /*\n * The spinner of the loading toast and of an upload that is going on. It turns itself, inside\n * the svg (`animateTransform`, around the centre of the ring), instead of being turned by a\n * css `animate-spin` on the svg: the browser then draws the ring again at the exact angle on\n * every frame. A css turn rotates a picture of the whole svg, and on a screen with a scaling of\n * 125% an icon of 20px is 25 device pixels, so the middle of that picture is half a pixel off\n * and the ring jumps up and down a little while it turns. Do not add `animate-spin` to it.\n */\n 'loading-spin': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M17 3.34A10 10 0 1 0 22 12\"><animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\"/></path>',\n },\n },\n },\n {\n prefix: 'lucide',\n width: 24,\n height: 24,\n icons: {\n // the close button of a closable toast\n x: {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M18 6L6 18M6 6l12 12\"/>',\n },\n },\n },\n];\n\n/**\n * Registers the icons above with Iconify (calling it again is harmless). It is a function that\n * `ToastContainer` calls, and not something that happens when this file is imported, on purpose: a\n * bare `import './toast-icons.js'` is dropped by the bundler when the package's `sideEffects` field\n * does not list the file (the build says \"ignored-bare-import\"), and then the icons are missing.\n */\nexport const registerToastIcons = () => {\n for (const iconSet of TOAST_ICON_SETS) addCollection(iconSet);\n};\n\n/** Every icon name registered above, e.g. `solar:danger-triangle-linear`. */\nexport const TOAST_ICON_NAMES = TOAST_ICON_SETS.flatMap(({ prefix, icons }) =>\n Object.keys(icons).map((name) => `${prefix}:${name}`),\n);\n","import type { IButton } from '../types/component.js';\n\ntype TPattern = IButton['pattern'];\n\n// A `Record`: adding a pattern to the type is a type error here until it has a look.\nconst PATTERN_CSS: Record<TPattern, string> = {\n primary: 'text-white bg-sky-blue-burst shadow-primary-btn hover:shadow-primary-btn-hover',\n secondary:\n 'text-secondary-invert bg-secondary shadow-secondary-btn hover:shadow-secondary-btn-hover',\n tertiary: 'text-tertiary-invert bg-tertiary shadow-tertiary-btn hover:shadow-tertiary-btn-hover',\n outline: 'text-primary border border-primary shadow-outline-btn hover:shadow-outline-btn-hover',\n transparent: 'bg-transparent border border-primary/30 text-secondary',\n};\n\n/** The look of a pattern; a pattern nobody knows (from code that is not type checked) is transparent. */\nexport const getButtonCss = (pattern: TPattern) =>\n Object.hasOwn(PATTERN_CSS, pattern) ? PATTERN_CSS[pattern] : PATTERN_CSS.transparent;\n","import { Icon } from '@iconify/react';\nimport { twMerge } from 'tailwind-merge';\n\nimport { getButtonCss } from '../lib/button.js';\nimport type { IButton } from '../types/component.js';\n\nconst BASE_CSS =\n 'group flex w-full cursor-pointer items-center justify-center gap-1 rounded-lg px-4 py-3 text-sm leading-4 transition-all duration-300 disabled:cursor-not-allowed disabled:opacity-85 lg:px-5 lg:py-4 xl:text-base';\n\nexport const Button = ({\n pattern,\n content,\n className = '',\n leftIcon,\n rightIcon,\n buttonProps,\n ref,\n}: IButton) => (\n // A class that is given wins over the one it clashes with (`rounded-md` over `rounded-lg`),\n // with no `!`; one for another screen size (`lg:px-5`) is a different class and stays.\n <button\n {...buttonProps}\n ref={ref}\n className={twMerge(BASE_CSS, getButtonCss(pattern), className, buttonProps?.className)}\n type={buttonProps?.type ?? 'button'}\n >\n {leftIcon && <Icon {...leftIcon} />}\n {typeof content === 'object' ? <Icon {...content} /> : content}\n {rightIcon && <Icon {...rightIcon} />}\n </button>\n);\n","import { TOAST_TYPE } from '../lib/constants.js';\nimport { useToastStore } from './toast.store.js';\nimport type {\n ICustomToast,\n IDefaultToast,\n ILoadingToast,\n IProgressToast,\n IUploadItem,\n IUploadsToast,\n TProgressToastOptions,\n} from './types.js';\n\nconst { add, update, remove } = useToastStore.getState();\nexport const toaster = {\n success: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.success }),\n error: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.error }),\n warning: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.warning }),\n default: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.default }),\n loading: (data: Omit<ILoadingToast, 'type'>) => add({ ...data, type: TOAST_TYPE.loading }),\n custom: (data: ICustomToast) => add(data),\n progress: {\n start: (data: Omit<IProgressToast, 'type'>) => add({ ...data, type: TOAST_TYPE.progress }),\n update: (toastId: string, progress: number) => {\n update.progress(toastId, progress);\n },\n end: (toastId: string) => {\n remove(toastId);\n },\n },\n uploads: {\n start: (data: Omit<IUploadsToast, 'type'>) => add({ ...data, type: TOAST_TYPE.uploads }),\n update: (toastId: string, itemId: string, patch: Partial<Omit<IUploadItem, 'id'>>) => {\n update.uploadItem(toastId, itemId, patch);\n },\n },\n remove: (toastId: string) => {\n remove(toastId);\n },\n};\n\nexport const withProgressToast = async <T>({\n title,\n description,\n request,\n}: TProgressToastOptions<T>): Promise<T> => {\n const toastId = toaster.progress.start({ title, description, progress: 0 });\n\n try {\n const response = await request((event) => {\n if (!event.total) return;\n\n toaster.progress.update(toastId, Math.round((event.loaded * 100) / event.total));\n });\n\n toaster.progress.update(toastId, 100);\n\n return response;\n } finally {\n toaster.progress.end(toastId);\n }\n};\n","import { toaster } from './toaster.js';\nimport type {\n IUploadGroup,\n IUploadItem,\n IUploadItemHandle,\n TUploadItemStatus,\n TUploadProgressHandler,\n} from './types.js';\n\nconst sum = (numbers: number[]) => numbers.reduce((total, value) => total + value, 0);\n\n/* ===================== WHAT THE TOAST SHOWS ===================== */\n\nexport const isUploadItemSettled = ({ status }: Pick<IUploadItem, 'status'>) =>\n status === 'success' || status === 'error';\n\n/**\n * How many files of an upload are through. An upload is one request, so a file is known to be\n * through only once the server has answered; until then the files that were completely sent count,\n * except the last one (it may still be on its way to the storage). A failed upload has none.\n */\nexport const getUploadItemFilesDone = ({\n status,\n loaded,\n fileSizes,\n}: Pick<IUploadItem, 'status' | 'loaded' | 'fileSizes'>) => {\n if (status === 'success') return fileSizes.length;\n if (status !== 'uploading') return 0;\n\n let sent = 0;\n let bytes = 0;\n\n for (const size of fileSizes) {\n bytes += size;\n\n if (bytes > loaded) break;\n\n sent += 1;\n }\n\n return Math.min(sent, Math.max(fileSizes.length - 1, 0));\n};\n\n/** How far one upload is, 0 to 100. 100 is only for an upload the server has answered. */\nexport const getUploadItemPercent = ({\n status,\n loaded,\n total,\n}: Pick<IUploadItem, 'status' | 'loaded' | 'total'>) => {\n if (status === 'success') return 100;\n if (status === 'pending' || total <= 0) return 0;\n\n return Math.min(99, Math.round((Math.min(loaded, total) * 100) / total));\n};\n\nexport interface IUploadsSummary {\n /** Overall progress by bytes, 0 to 100. 100 only when every upload has succeeded. */\n percent: number;\n filesDone: number;\n filesTotal: number;\n /** How many uploads failed. */\n failed: number;\n /** Every upload has either succeeded or failed. */\n isSettled: boolean;\n}\n\nexport const getUploadsSummary = (items: IUploadItem[]): IUploadsSummary => {\n const failed = items.filter(({ status }) => status === 'error').length;\n const isSettled = items.every(isUploadItemSettled);\n const bytesTotal = sum(items.map(({ total }) => total));\n const bytesDone = sum(\n items.map((item) =>\n item.status === 'success' ? item.total : Math.min(item.loaded, item.total),\n ),\n );\n\n let percent = bytesTotal > 0 ? Math.round((bytesDone * 100) / bytesTotal) : 0;\n\n if (isSettled && failed === 0) percent = 100;\n else percent = Math.min(percent, 99);\n\n return {\n percent,\n filesDone: sum(items.map(getUploadItemFilesDone)),\n filesTotal: sum(items.map(({ fileSizes }) => fileSizes.length)),\n failed,\n isSettled,\n };\n};\n\n/* ===================== FILES ===================== */\n\n/** The files of a FormData, in the order they are sent. */\nexport const getFormDataFiles = (data: FormData, key = 'files'): File[] =>\n data.getAll(key).filter((value): value is File => value instanceof File);\n\n/* ===================== THE TOAST OF A GROUP OF UPLOADS ===================== */\n\ninterface IUploadGroupOptions {\n title: string;\n description?: string;\n items: { id: string; label: string; files: File[] }[];\n}\n\n/**\n * Opens one toast for the uploads of `items`. It closes by itself a moment after every upload is\n * over. Returns nothing when there is nothing to upload, so no empty toast is shown.\n */\nexport const createUploadsToast = ({\n title,\n description,\n items,\n}: IUploadGroupOptions): IUploadGroup | undefined => {\n if (items.length === 0) return undefined;\n\n const statuses = new Map<string, TUploadItemStatus>(items.map(({ id }) => [id, 'pending']));\n\n const toastId = toaster.uploads.start({\n title,\n description,\n items: items.map(({ id, label, files }) => {\n const fileSizes = files.map(({ size }) => size);\n\n return { id, label, status: 'pending', loaded: 0, total: sum(fileSizes), fileSizes };\n }),\n });\n\n const patch = (id: string, changes: Partial<Omit<IUploadItem, 'id'>>) => {\n if (changes.status) statuses.set(id, changes.status);\n\n toaster.uploads.update(toastId, id, changes);\n };\n\n return {\n item: (id) => ({\n run: async (request) => {\n patch(id, { status: 'uploading' });\n\n try {\n const result = await request((event) => {\n // The browser says nothing about the total for some requests: keep the size estimate then.\n if (!event.total) return;\n\n patch(id, { loaded: event.loaded, total: event.total });\n });\n\n patch(id, { status: 'success' });\n\n return result;\n } catch (error) {\n patch(id, { status: 'error' });\n\n throw error;\n }\n },\n }),\n\n end: () => {\n for (const [id, status] of statuses) {\n if (status === 'pending' || status === 'uploading') patch(id, { status: 'error' });\n }\n },\n };\n};\n\n/** The toast for a single request that uploads several files at once. */\nexport const withUploadsToast = async <T>({\n title,\n description,\n files,\n request,\n}: {\n title: string;\n description?: string;\n files: File[];\n request: (onProgress: TUploadProgressHandler) => Promise<T>;\n}): Promise<T> => {\n const group = createUploadsToast({\n title,\n description,\n items: files.length > 0 ? [{ id: 'files', label: description ?? title, files }] : [],\n });\n\n if (!group) return request(() => undefined);\n\n try {\n return await group.item('files').run(request);\n } finally {\n group.end();\n }\n};\n\n/**\n * Runs the uploads of several fields (e.g. the images of each editor of a form step) behind one\n * toast with a row for every field that has files. `run` is called for every field, with the row of\n * that field to give to its upload (nothing when the toast has no row for it). Every upload is\n * waited for, so none is shown as failed just because another one failed; if any failed, the first\n * error is thrown once all are over.\n */\nexport const runUploadsInToast = async <TId extends string, TResult>({\n title,\n description,\n uploads,\n run,\n}: {\n title: string;\n description?: string;\n uploads: { id: TId; label: string; files: File[] }[];\n run: (id: TId, progress: IUploadItemHandle | undefined) => Promise<TResult>;\n}): Promise<Record<TId, TResult>> => {\n const group = createUploadsToast({\n title,\n description,\n items: uploads.filter(({ files }) => files.length > 0),\n });\n\n const settled = await Promise.allSettled(uploads.map(({ id }) => run(id, group?.item(id))));\n\n group?.end();\n\n const results = {} as Record<TId, TResult>;\n\n settled.forEach((result, index) => {\n if (result.status === 'fulfilled') results[uploads[index].id] = result.value;\n });\n\n const failure = settled.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n );\n\n if (failure) {\n throw failure.reason instanceof Error ? failure.reason : new Error('Upload failed');\n }\n\n return results;\n};\n","import { Icon } from '@iconify/react';\nimport { type ComponentProps, memo, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { TOAST_TYPE } from '../lib/constants.js';\nimport type { IClassName } from '../types/component.js';\nimport { Button } from '../ui/Button.js';\nimport { registerToastIcons } from './toast-icons.js';\nimport { useToastStore } from './toast.store.js';\nimport type { IUploadItem, TToast, TToastItem, TUploadItemStatus } from './types.js';\nimport {\n getUploadItemFilesDone,\n getUploadItemPercent,\n getUploadsSummary,\n type IUploadsSummary,\n} from './uploads.js';\n\n// Bundles the icons the toasts use, so they also show without a network (see toast-icons.ts)\nregisterToastIcons();\n\nconst CircularProgress = ({ progress, ...props }: { progress: number } & ComponentProps<'svg'>) => {\n const radius = 10;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference - (progress / 100) * circumference;\n\n return (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" {...props}>\n <circle\n cx=\"12\"\n cy=\"12\"\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeOpacity={0.15}\n strokeWidth=\"1.5\"\n />\n <circle\n cx=\"12\"\n cy=\"12\"\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n transform=\"rotate(-90 12 12)\"\n />\n\n <text\n x=\"12\"\n y=\"12\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fontSize=\"6\"\n fontWeight=\"500\"\n fill=\"currentColor\"\n >\n {progress}%\n </text>\n </svg>\n );\n};\n\nconst GREEN_RGB = 'var(--primary-green-rgb)';\nconst RED_RGB = 'var(--primary-red-rgb)';\n\nconst UPLOAD_ITEM_ICON: Record<TUploadItemStatus, { icon: string; rgb: string }> = {\n pending: { icon: 'solar:clock-circle-linear', rgb: 'var(--primary-rgb)' },\n uploading: { icon: 'beautinique:loading-spin', rgb: 'var(--primary-rgb)' },\n success: { icon: 'solar:check-circle-linear', rgb: GREEN_RGB },\n error: { icon: 'solar:danger-triangle-linear', rgb: RED_RGB },\n};\n\n/** The colour of an uploads toast follows how its uploads are doing. */\nconst uploadsRgb = ({ isSettled, failed }: IUploadsSummary) => {\n if (!isSettled) return 'var(--primary-rgb)';\n\n return failed > 0 ? RED_RGB : GREEN_RGB;\n};\n\nconst uploadsSummaryText = ({ filesDone, filesTotal, failed, isSettled }: IUploadsSummary) => {\n if (!isSettled) return `${String(filesDone)} of ${String(filesTotal)} uploaded`;\n if (failed === 0) return filesTotal === 1 ? 'Uploaded' : `All ${String(filesTotal)} uploaded`;\n\n return `${String(filesDone)} of ${String(filesTotal)} uploaded, ${String(failed)} failed`;\n};\n\n/** While uploading the title is the caller's (e.g. \"Please wait...\"); once over it says how it went. */\nconst uploadsHeading = (title: string, { failed, isSettled }: IUploadsSummary, uploads: number) => {\n if (!isSettled) return title;\n if (failed === 0) return 'Upload complete';\n\n return failed === uploads ? 'Upload failed' : 'Some uploads failed';\n};\n\nconst UploadRow = ({ item }: { item: IUploadItem }) => {\n const percent = getUploadItemPercent(item);\n const { icon, rgb } = UPLOAD_ITEM_ICON[item.status];\n\n return (\n <li data-status={item.status} className=\"flex items-center gap-1.5 md:gap-2\">\n <Icon\n icon={icon}\n className=\"size-3.5 shrink-0 md:size-4\"\n style={{ color: `rgb(${rgb})`, opacity: item.status === 'pending' ? 0.4 : 1 }}\n />\n\n <span className=\"text-primary w-20 shrink-0 truncate text-[9px] md:w-28 md:text-xs\">\n {item.label}\n </span>\n\n <div\n role=\"progressbar\"\n aria-label={`${item.label} upload`}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={percent}\n className=\"bg-primary/10 h-1 min-w-0 flex-1 overflow-hidden rounded-full\"\n >\n <div\n className=\"h-full rounded-full transition-[width] duration-300\"\n style={{ width: `${String(percent)}%`, backgroundColor: `rgb(${rgb})` }}\n />\n </div>\n\n <span className=\"text-tertiary w-8 shrink-0 text-right text-[9px] tabular-nums md:text-xs\">\n {getUploadItemFilesDone(item)}/{item.fileSizes.length}\n </span>\n </li>\n );\n};\n\ninterface IUploadsBodyProps {\n title: string;\n description?: string;\n items: IUploadItem[];\n summary: IUploadsSummary;\n rgb: string;\n}\n\nconst UploadsBody = ({ title, description, items, summary, rgb }: IUploadsBodyProps) => (\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\" aria-live=\"polite\">\n <div className=\"flex flex-col gap-0.5\">\n <p className=\"line-clamp-1 text-xs font-semibold md:text-sm\" style={{ color: `rgb(${rgb})` }}>\n {uploadsHeading(title, summary, items.length)}\n </p>\n\n {description && (\n <p className=\"text-tertiary line-clamp-1 text-[9px]/3 md:text-xs\">{description}</p>\n )}\n\n <p className=\"text-tertiary text-[9px]/3 tabular-nums md:text-xs\">\n {uploadsSummaryText(summary)}\n </p>\n </div>\n\n {items.length > 1 && (\n <ul className=\"flex flex-col gap-1\">\n {items.map((item) => (\n <UploadRow key={item.id} item={item} />\n ))}\n </ul>\n )}\n </div>\n);\n\nconst cardConfig = (type: TToast['type']) => {\n switch (type) {\n case TOAST_TYPE.success:\n return { iconName: 'solar:check-circle-linear', rgb: GREEN_RGB };\n case TOAST_TYPE.error:\n return { iconName: 'solar:danger-triangle-linear', rgb: RED_RGB };\n case TOAST_TYPE.warning:\n return { iconName: 'solar:danger-triangle-linear', rgb: 'var(--primary-yellow-rgb)' };\n case TOAST_TYPE.progress:\n case TOAST_TYPE.uploads:\n return { iconName: '', rgb: 'var(--primary-rgb)' };\n case TOAST_TYPE.loading:\n return { iconName: 'beautinique:loading-spin', rgb: 'var(--primary-rgb)' };\n case TOAST_TYPE.default:\n case TOAST_TYPE.custom:\n default:\n return { iconName: 'solar:info-circle-outline', rgb: 'var(--primary-rgb)' };\n }\n};\n\nconst ToasterItem = (props: TToastItem & IClassName) => {\n const {\n className = '',\n type,\n icon,\n buttonProps,\n isClosable = true,\n autoClose = true,\n closeTimer = 5000,\n } = props;\n\n const remove = useToastStore((s) => s.remove);\n\n const [visible, setVisible] = useState(false);\n const [mounted, setMounted] = useState(true);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // An uploads toast stays while anything is still uploading, then closes by itself (later when\n // something failed, so it can be read).\n const uploadsSummary = props.type === TOAST_TYPE.uploads ? getUploadsSummary(props.items) : null;\n const isUploadsSettled = uploadsSummary?.isSettled ?? false;\n\n let resolvedAutoClose = autoClose;\n let resolvedIsClosable = isClosable;\n let resolvedCloseTimer = closeTimer;\n\n if (TOAST_TYPE.loading === type || TOAST_TYPE.progress === type) {\n resolvedAutoClose = false;\n resolvedIsClosable = false;\n } else if (uploadsSummary) {\n resolvedAutoClose = isUploadsSettled;\n resolvedIsClosable = isUploadsSettled;\n resolvedCloseTimer = uploadsSummary.failed > 0 ? 8000 : 2500;\n }\n\n const config = uploadsSummary\n ? { iconName: '', rgb: uploadsRgb(uploadsSummary) }\n : cardConfig(type);\n\n const handleClose = useCallback(() => {\n setVisible(false);\n\n timeoutRef.current = setTimeout(() => {\n setMounted(false);\n remove(props.id);\n }, 300);\n }, [remove, props.id]);\n\n useEffect(() => {\n const enterTimer = setTimeout(() => {\n setVisible(true);\n }, 50);\n\n let autoTimer: ReturnType<typeof setTimeout> | null = null;\n\n if (resolvedAutoClose) {\n autoTimer = setTimeout(() => {\n handleClose();\n }, resolvedCloseTimer);\n }\n\n return () => {\n clearTimeout(enterTimer);\n if (autoTimer) clearTimeout(autoTimer);\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, [resolvedAutoClose, resolvedCloseTimer, handleClose]);\n\n if (!mounted) return null;\n\n const isCustom = type === TOAST_TYPE.custom;\n\n return (\n <div\n className={`rounded-xl border-2 transition-all duration-300 ease-in-out ${\n visible ? 'translate-x-0 opacity-100' : 'translate-x-full opacity-0'\n } ${className}`}\n style={{\n borderColor: `rgba(${config.rgb}, 0.2)`,\n boxShadow: `0 10px 10px 0px rgba(${config.rgb}, 0.1)`,\n }}\n >\n <div className=\"bg-secondary-invert flex w-full items-center gap-2 rounded-[10.25px] p-1.5 md:p-2.5 lg:p-3 [&>svg]:size-5 [&>svg]:shrink-0 [&>svg]:md:size-6 [&>svg]:lg:size-7\">\n {icon ??\n (props.type === TOAST_TYPE.progress ? (\n <CircularProgress\n progress={props.progress}\n style={{ strokeColor: `rgb(${config.rgb})` }}\n />\n ) : uploadsSummary ? (\n <CircularProgress\n progress={uploadsSummary.percent}\n style={{ color: `rgb(${config.rgb})` }}\n />\n ) : (\n <Icon icon={config.iconName} style={{ color: `rgb(${config.rgb})` }} />\n ))}\n\n {props.type === TOAST_TYPE.uploads && uploadsSummary ? (\n <UploadsBody\n title={props.title}\n description={props.description}\n items={props.items}\n summary={uploadsSummary}\n rgb={config.rgb}\n />\n ) : (\n <div className=\"flex flex-1 items-center justify-between gap-2\">\n <div className=\"flex flex-col gap-0.5\">\n {!isCustom && 'title' in props && (\n <p\n className=\"line-clamp-1 text-xs font-semibold md:text-sm\"\n style={{ color: `rgb(${config.rgb})` }}\n >\n {props.title}\n </p>\n )}\n\n {!isCustom && 'description' in props && (\n <p className=\"text-tertiary line-clamp-2 text-[9px]/3 whitespace-pre-line md:text-xs\">\n {props.description}\n </p>\n )}\n {isCustom && 'children' in props && props.children}\n </div>\n\n {buttonProps && type !== TOAST_TYPE.loading && type !== TOAST_TYPE.progress && (\n <Button\n {...buttonProps}\n content={buttonProps.content ?? 'Try Again'}\n pattern={buttonProps.pattern ?? 'secondary'}\n className={`w-fit! rounded-md! px-2! py-1! pt-1.5! text-[10px] whitespace-nowrap md:text-xs! ${buttonProps.className ?? ''}`}\n />\n )}\n </div>\n )}\n\n {resolvedIsClosable && (\n <Icon\n icon=\"lucide:x\"\n className=\"text-primary cursor-pointer md:size-5\"\n onClick={handleClose}\n />\n )}\n </div>\n </div>\n );\n};\n\n/*\n * The store changes only the toast that was updated (the others keep the same object), and a toast\n * that is uploading is updated many times a second. With `memo` the toasts that did not change\n * are not rendered again for each of those updates.\n */\nexport const Toaster = memo(ToasterItem);\n\nexport const ToastContainer = () => {\n const toasts = useToastStore((s) => s.toasts);\n\n if (toasts.length === 0) return null;\n\n return (\n <div className=\"base:max-w-sm fixed right-2 bottom-2 z-999 flex w-full max-w-xs flex-col gap-2 sm:max-w-md md:right-4 md:bottom-4 md:max-w-lg lg:right-8 lg:bottom-8 lg:max-w-xl\">\n {toasts.map((toast) => (\n <Toaster key={toast.id} {...toast} id={toast.id} />\n ))}\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/constants.ts","../../src/toast/toast.store.ts","../../src/toast/toast-icons.ts","../../src/lib/button.ts","../../src/ui/Button.tsx","../../src/toast/toaster.ts","../../src/toast/uploads.ts","../../src/toast/ToastContainer.tsx"],"names":["jsxs","jsx","Icon","remove"],"mappings":"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","file":"index.js","sourcesContent":["export const TOOLTIP_GAP = 15 as const;\nexport const TOOLTIP_ANIMATION_DURATION = 400 as const;\n/** The least space a tooltip keeps between itself and the edge of the window. */\nexport const TOOLTIP_VIEWPORT_MARGIN = 8 as const;\n/** The arrow stays at least this far from the ends of the tooltip (its own size and the rounded corner). */\nexport const TOOLTIP_ARROW_INSET = 16 as const;\n\nexport const TOAST_TYPES = [\n 'success',\n 'error',\n 'warning',\n 'progress',\n 'uploads',\n 'loading',\n 'default',\n 'custom',\n] as const;\n\nexport const TOAST_TYPE = Object.fromEntries(TOAST_TYPES.map((type) => [type, type])) as {\n [K in (typeof TOAST_TYPES)[number]]: K;\n};\n","import { nanoid } from 'nanoid';\nimport { create } from 'zustand';\n\nimport { TOAST_TYPE } from '../lib/constants.js';\nimport type { IToastStore } from './types.js';\n\nconst useToastStore = create<IToastStore>((set) => ({\n toasts: [],\n\n add: (toast) => {\n const id = nanoid();\n\n set((state) => ({ toasts: [...state.toasts, { ...toast, id }] }));\n\n return id; // return the id of the toast for removal\n },\n\n update: {\n progress: (id, progress) => {\n set((state) => ({\n toasts: state.toasts.map((toast) => (toast.id === id ? { ...toast, progress } : toast)),\n }));\n },\n\n uploadItem: (id, itemId, patch) => {\n set((state) => ({\n toasts: state.toasts.map((toast) =>\n toast.id === id && toast.type === TOAST_TYPE.uploads\n ? {\n ...toast,\n items: toast.items.map((item) =>\n item.id === itemId ? { ...item, ...patch } : item,\n ),\n }\n : toast,\n ),\n }));\n },\n },\n\n remove: (id) => {\n set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));\n },\n}));\n\nexport { useToastStore };\n","import { addCollection, type IconifyJSON } from '@iconify/react';\n\n/*\n * Iconify downloads an icon's SVG from its API the first time the icon is shown, and keeps it in\n * memory. A toast's icon is very often needed for the first time exactly when the download cannot\n * work: the \"You're offline\" toast, or the error toast of a request that failed because there is no\n * internet. Those icons are bundled here, so every toast has its icon without a network.\n *\n * Add an icon here when a toast starts using one (see `cardConfig` in `components/ui/Toaster.tsx`).\n * The data is what `https://api.iconify.design/<prefix>.json?icons=<name>` answers.\n */\nconst TOAST_ICON_SETS: IconifyJSON[] = [\n {\n prefix: 'solar',\n width: 24,\n height: 24,\n icons: {\n // warning and error toasts\n 'danger-triangle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><path d=\"M5.31171 10.7615C8.23007 5.58716 9.68925 3 12 3C14.3107 3 15.7699 5.58716 18.6883 10.7615L19.0519 11.4063C21.4771 15.7061 22.6897 17.856 21.5937 19.428C20.4978 21 17.7864 21 12.3637 21H11.6363C6.21356 21 3.50217 21 2.40626 19.428C1.31034 17.856 2.52291 15.7061 4.94805 11.4063L5.31171 10.7615Z\"/><path d=\"M12 8V13\"/><path stroke-linejoin=\"round\" d=\"M12 16H12.0001\"/></g>',\n },\n // success toast\n 'check-circle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path stroke-linejoin=\"round\" d=\"M8.5 12.5L10.5 14.5L15.5 9.5\"/></g>',\n },\n // an upload that is waiting its turn, in an uploads toast\n 'clock-circle-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path stroke-linejoin=\"round\" d=\"M12 8V12L14.5 14.5\"/></g>',\n },\n // default and custom toasts\n 'info-circle-outline': {\n body: '<g fill=\"currentColor\"><path d=\"M12 17.75C12.4142 17.75 12.75 17.4142 12.75 17V11C12.75 10.5858 12.4142 10.25 12 10.25C11.5858 10.25 11.25 10.5858 11.25 11V17C11.25 17.4142 11.5858 17.75 12 17.75Z\"/><path d=\"M12 7C12.5523 7 13 7.44772 13 8C13 8.55228 12.5523 9 12 9C11.4477 9 11 8.55228 11 8C11 7.44772 11.4477 7 12 7Z\"/><path fill-rule=\"evenodd\" d=\"M1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12ZM12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.9371 2.75 12 2.75Z\" clip-rule=\"evenodd\"/></g>',\n },\n },\n },\n {\n prefix: 'beautinique',\n width: 24,\n height: 24,\n icons: {\n /*\n * The spinner of the loading toast and of an upload that is going on. It turns itself, inside\n * the svg (`animateTransform`, around the centre of the ring), instead of being turned by a\n * css `animate-spin` on the svg: the browser then draws the ring again at the exact angle on\n * every frame. A css turn rotates a picture of the whole svg, and on a screen with a scaling of\n * 125% an icon of 20px is 25 device pixels, so the middle of that picture is half a pixel off\n * and the ring jumps up and down a little while it turns. Do not add `animate-spin` to it.\n */\n 'loading-spin': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M17 3.34A10 10 0 1 0 22 12\"><animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\"/></path>',\n },\n },\n },\n {\n prefix: 'lucide',\n width: 24,\n height: 24,\n icons: {\n // the close button of a closable toast\n x: {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M18 6L6 18M6 6l12 12\"/>',\n },\n },\n },\n];\n\n/**\n * Registers the icons above with Iconify (calling it again is harmless). It is a function that\n * `ToastContainer` calls, and not something that happens when this file is imported, on purpose: a\n * bare `import './toast-icons.js'` is dropped by the bundler when the package's `sideEffects` field\n * does not list the file (the build says \"ignored-bare-import\"), and then the icons are missing.\n */\nexport const registerToastIcons = () => {\n for (const iconSet of TOAST_ICON_SETS) addCollection(iconSet);\n};\n\n/** Every icon name registered above, e.g. `solar:danger-triangle-linear`. */\nexport const TOAST_ICON_NAMES = TOAST_ICON_SETS.flatMap(({ prefix, icons }) =>\n Object.keys(icons).map((name) => `${prefix}:${name}`),\n);\n","import type { IButton } from '../types/component.js';\n\ntype TPattern = IButton['pattern'];\n\n// A `Record`: adding a pattern to the type is a type error here until it has a look.\nconst PATTERN_CSS: Record<TPattern, string> = {\n primary: 'text-white bg-sky-blue-burst shadow-primary-btn hover:shadow-primary-btn-hover',\n secondary:\n 'text-secondary-invert bg-secondary shadow-secondary-btn hover:shadow-secondary-btn-hover',\n tertiary: 'text-tertiary-invert bg-tertiary shadow-tertiary-btn hover:shadow-tertiary-btn-hover',\n outline: 'text-primary border border-primary shadow-outline-btn hover:shadow-outline-btn-hover',\n transparent: 'bg-transparent border border-primary/30 text-secondary',\n};\n\n/** The look of a pattern; a pattern nobody knows (from code that is not type checked) is transparent. */\nexport const getButtonCss = (pattern: TPattern) =>\n Object.hasOwn(PATTERN_CSS, pattern) ? PATTERN_CSS[pattern] : PATTERN_CSS.transparent;\n","import { Icon } from '@iconify/react';\n\nimport { getButtonCss } from '../lib/button.js';\nimport type { IButton } from '../types/component.js';\n\nconst BASE_CSS =\n 'group flex w-full cursor-pointer items-center justify-center gap-1 rounded-lg px-4 py-3 text-sm leading-4 transition-all duration-300 disabled:cursor-not-allowed disabled:opacity-85 lg:px-5 lg:py-4 xl:text-base';\n\nexport const Button = ({\n pattern,\n content,\n className = '',\n leftIcon,\n rightIcon,\n buttonProps,\n ref,\n}: IButton) => (\n // The classes that are given come last but do not remove the button's own: to win over one of\n // them give it with `!` (`rounded-md!`), the way the toast's button does.\n <button\n {...buttonProps}\n ref={ref}\n className={`${BASE_CSS} ${getButtonCss(pattern)} ${className} ${buttonProps?.className ?? ''}`}\n type={buttonProps?.type ?? 'button'}\n >\n {leftIcon && <Icon {...leftIcon} />}\n {typeof content === 'object' ? <Icon {...content} /> : content}\n {rightIcon && <Icon {...rightIcon} />}\n </button>\n);\n","import { TOAST_TYPE } from '../lib/constants.js';\nimport { useToastStore } from './toast.store.js';\nimport type {\n ICustomToast,\n IDefaultToast,\n ILoadingToast,\n IProgressToast,\n IUploadItem,\n IUploadsToast,\n TProgressToastOptions,\n} from './types.js';\n\nconst { add, update, remove } = useToastStore.getState();\nexport const toaster = {\n success: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.success }),\n error: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.error }),\n warning: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.warning }),\n default: (data: Omit<IDefaultToast, 'type'>) => add({ ...data, type: TOAST_TYPE.default }),\n loading: (data: Omit<ILoadingToast, 'type'>) => add({ ...data, type: TOAST_TYPE.loading }),\n custom: (data: ICustomToast) => add(data),\n progress: {\n start: (data: Omit<IProgressToast, 'type'>) => add({ ...data, type: TOAST_TYPE.progress }),\n update: (toastId: string, progress: number) => {\n update.progress(toastId, progress);\n },\n end: (toastId: string) => {\n remove(toastId);\n },\n },\n uploads: {\n start: (data: Omit<IUploadsToast, 'type'>) => add({ ...data, type: TOAST_TYPE.uploads }),\n update: (toastId: string, itemId: string, patch: Partial<Omit<IUploadItem, 'id'>>) => {\n update.uploadItem(toastId, itemId, patch);\n },\n },\n remove: (toastId: string) => {\n remove(toastId);\n },\n};\n\nexport const withProgressToast = async <T>({\n title,\n description,\n request,\n}: TProgressToastOptions<T>): Promise<T> => {\n const toastId = toaster.progress.start({ title, description, progress: 0 });\n\n try {\n const response = await request((event) => {\n if (!event.total) return;\n\n toaster.progress.update(toastId, Math.round((event.loaded * 100) / event.total));\n });\n\n toaster.progress.update(toastId, 100);\n\n return response;\n } finally {\n toaster.progress.end(toastId);\n }\n};\n","import { toaster } from './toaster.js';\nimport type {\n IUploadGroup,\n IUploadItem,\n IUploadItemHandle,\n TUploadItemStatus,\n TUploadProgressHandler,\n} from './types.js';\n\nconst sum = (numbers: number[]) => numbers.reduce((total, value) => total + value, 0);\n\n/* ===================== WHAT THE TOAST SHOWS ===================== */\n\nexport const isUploadItemSettled = ({ status }: Pick<IUploadItem, 'status'>) =>\n status === 'success' || status === 'error';\n\n/**\n * How many files of an upload are through. An upload is one request, so a file is known to be\n * through only once the server has answered; until then the files that were completely sent count,\n * except the last one (it may still be on its way to the storage). A failed upload has none.\n */\nexport const getUploadItemFilesDone = ({\n status,\n loaded,\n fileSizes,\n}: Pick<IUploadItem, 'status' | 'loaded' | 'fileSizes'>) => {\n if (status === 'success') return fileSizes.length;\n if (status !== 'uploading') return 0;\n\n let sent = 0;\n let bytes = 0;\n\n for (const size of fileSizes) {\n bytes += size;\n\n if (bytes > loaded) break;\n\n sent += 1;\n }\n\n return Math.min(sent, Math.max(fileSizes.length - 1, 0));\n};\n\n/** How far one upload is, 0 to 100. 100 is only for an upload the server has answered. */\nexport const getUploadItemPercent = ({\n status,\n loaded,\n total,\n}: Pick<IUploadItem, 'status' | 'loaded' | 'total'>) => {\n if (status === 'success') return 100;\n if (status === 'pending' || total <= 0) return 0;\n\n return Math.min(99, Math.round((Math.min(loaded, total) * 100) / total));\n};\n\nexport interface IUploadsSummary {\n /** Overall progress by bytes, 0 to 100. 100 only when every upload has succeeded. */\n percent: number;\n filesDone: number;\n filesTotal: number;\n /** How many uploads failed. */\n failed: number;\n /** Every upload has either succeeded or failed. */\n isSettled: boolean;\n}\n\nexport const getUploadsSummary = (items: IUploadItem[]): IUploadsSummary => {\n const failed = items.filter(({ status }) => status === 'error').length;\n const isSettled = items.every(isUploadItemSettled);\n const bytesTotal = sum(items.map(({ total }) => total));\n const bytesDone = sum(\n items.map((item) =>\n item.status === 'success' ? item.total : Math.min(item.loaded, item.total),\n ),\n );\n\n let percent = bytesTotal > 0 ? Math.round((bytesDone * 100) / bytesTotal) : 0;\n\n if (isSettled && failed === 0) percent = 100;\n else percent = Math.min(percent, 99);\n\n return {\n percent,\n filesDone: sum(items.map(getUploadItemFilesDone)),\n filesTotal: sum(items.map(({ fileSizes }) => fileSizes.length)),\n failed,\n isSettled,\n };\n};\n\n/* ===================== FILES ===================== */\n\n/** The files of a FormData, in the order they are sent. */\nexport const getFormDataFiles = (data: FormData, key = 'files'): File[] =>\n data.getAll(key).filter((value): value is File => value instanceof File);\n\n/* ===================== THE TOAST OF A GROUP OF UPLOADS ===================== */\n\ninterface IUploadGroupOptions {\n title: string;\n description?: string;\n items: { id: string; label: string; files: File[] }[];\n}\n\n/**\n * Opens one toast for the uploads of `items`. It closes by itself a moment after every upload is\n * over. Returns nothing when there is nothing to upload, so no empty toast is shown.\n */\nexport const createUploadsToast = ({\n title,\n description,\n items,\n}: IUploadGroupOptions): IUploadGroup | undefined => {\n if (items.length === 0) return undefined;\n\n const statuses = new Map<string, TUploadItemStatus>(items.map(({ id }) => [id, 'pending']));\n\n const toastId = toaster.uploads.start({\n title,\n description,\n items: items.map(({ id, label, files }) => {\n const fileSizes = files.map(({ size }) => size);\n\n return { id, label, status: 'pending', loaded: 0, total: sum(fileSizes), fileSizes };\n }),\n });\n\n const patch = (id: string, changes: Partial<Omit<IUploadItem, 'id'>>) => {\n if (changes.status) statuses.set(id, changes.status);\n\n toaster.uploads.update(toastId, id, changes);\n };\n\n return {\n item: (id) => ({\n run: async (request) => {\n patch(id, { status: 'uploading' });\n\n try {\n const result = await request((event) => {\n // The browser says nothing about the total for some requests: keep the size estimate then.\n if (!event.total) return;\n\n patch(id, { loaded: event.loaded, total: event.total });\n });\n\n patch(id, { status: 'success' });\n\n return result;\n } catch (error) {\n patch(id, { status: 'error' });\n\n throw error;\n }\n },\n }),\n\n end: () => {\n for (const [id, status] of statuses) {\n if (status === 'pending' || status === 'uploading') patch(id, { status: 'error' });\n }\n },\n };\n};\n\n/** The toast for a single request that uploads several files at once. */\nexport const withUploadsToast = async <T>({\n title,\n description,\n files,\n request,\n}: {\n title: string;\n description?: string;\n files: File[];\n request: (onProgress: TUploadProgressHandler) => Promise<T>;\n}): Promise<T> => {\n const group = createUploadsToast({\n title,\n description,\n items: files.length > 0 ? [{ id: 'files', label: description ?? title, files }] : [],\n });\n\n if (!group) return request(() => undefined);\n\n try {\n return await group.item('files').run(request);\n } finally {\n group.end();\n }\n};\n\n/**\n * Runs the uploads of several fields (e.g. the images of each editor of a form step) behind one\n * toast with a row for every field that has files. `run` is called for every field, with the row of\n * that field to give to its upload (nothing when the toast has no row for it). Every upload is\n * waited for, so none is shown as failed just because another one failed; if any failed, the first\n * error is thrown once all are over.\n */\nexport const runUploadsInToast = async <TId extends string, TResult>({\n title,\n description,\n uploads,\n run,\n}: {\n title: string;\n description?: string;\n uploads: { id: TId; label: string; files: File[] }[];\n run: (id: TId, progress: IUploadItemHandle | undefined) => Promise<TResult>;\n}): Promise<Record<TId, TResult>> => {\n const group = createUploadsToast({\n title,\n description,\n items: uploads.filter(({ files }) => files.length > 0),\n });\n\n const settled = await Promise.allSettled(uploads.map(({ id }) => run(id, group?.item(id))));\n\n group?.end();\n\n const results = {} as Record<TId, TResult>;\n\n settled.forEach((result, index) => {\n if (result.status === 'fulfilled') results[uploads[index].id] = result.value;\n });\n\n const failure = settled.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n );\n\n if (failure) {\n throw failure.reason instanceof Error ? failure.reason : new Error('Upload failed');\n }\n\n return results;\n};\n","import { Icon } from '@iconify/react';\nimport { type ComponentProps, memo, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { TOAST_TYPE } from '../lib/constants.js';\nimport type { IClassName } from '../types/component.js';\nimport { Button } from '../ui/Button.js';\nimport { registerToastIcons } from './toast-icons.js';\nimport { useToastStore } from './toast.store.js';\nimport type { IUploadItem, TToast, TToastItem, TUploadItemStatus } from './types.js';\nimport {\n getUploadItemFilesDone,\n getUploadItemPercent,\n getUploadsSummary,\n type IUploadsSummary,\n} from './uploads.js';\n\n// Bundles the icons the toasts use, so they also show without a network (see toast-icons.ts)\nregisterToastIcons();\n\nconst CircularProgress = ({ progress, ...props }: { progress: number } & ComponentProps<'svg'>) => {\n const radius = 10;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference - (progress / 100) * circumference;\n\n return (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" {...props}>\n <circle\n cx=\"12\"\n cy=\"12\"\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeOpacity={0.15}\n strokeWidth=\"1.5\"\n />\n <circle\n cx=\"12\"\n cy=\"12\"\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n transform=\"rotate(-90 12 12)\"\n />\n\n <text\n x=\"12\"\n y=\"12\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fontSize=\"6\"\n fontWeight=\"500\"\n fill=\"currentColor\"\n >\n {progress}%\n </text>\n </svg>\n );\n};\n\nconst GREEN_RGB = 'var(--primary-green-rgb)';\nconst RED_RGB = 'var(--primary-red-rgb)';\n\nconst UPLOAD_ITEM_ICON: Record<TUploadItemStatus, { icon: string; rgb: string }> = {\n pending: { icon: 'solar:clock-circle-linear', rgb: 'var(--primary-rgb)' },\n uploading: { icon: 'beautinique:loading-spin', rgb: 'var(--primary-rgb)' },\n success: { icon: 'solar:check-circle-linear', rgb: GREEN_RGB },\n error: { icon: 'solar:danger-triangle-linear', rgb: RED_RGB },\n};\n\n/** The colour of an uploads toast follows how its uploads are doing. */\nconst uploadsRgb = ({ isSettled, failed }: IUploadsSummary) => {\n if (!isSettled) return 'var(--primary-rgb)';\n\n return failed > 0 ? RED_RGB : GREEN_RGB;\n};\n\nconst uploadsSummaryText = ({ filesDone, filesTotal, failed, isSettled }: IUploadsSummary) => {\n if (!isSettled) return `${String(filesDone)} of ${String(filesTotal)} uploaded`;\n if (failed === 0) return filesTotal === 1 ? 'Uploaded' : `All ${String(filesTotal)} uploaded`;\n\n return `${String(filesDone)} of ${String(filesTotal)} uploaded, ${String(failed)} failed`;\n};\n\n/** While uploading the title is the caller's (e.g. \"Please wait...\"); once over it says how it went. */\nconst uploadsHeading = (title: string, { failed, isSettled }: IUploadsSummary, uploads: number) => {\n if (!isSettled) return title;\n if (failed === 0) return 'Upload complete';\n\n return failed === uploads ? 'Upload failed' : 'Some uploads failed';\n};\n\nconst UploadRow = ({ item }: { item: IUploadItem }) => {\n const percent = getUploadItemPercent(item);\n const { icon, rgb } = UPLOAD_ITEM_ICON[item.status];\n\n return (\n <li data-status={item.status} className=\"flex items-center gap-1.5 md:gap-2\">\n <Icon\n icon={icon}\n className=\"size-3.5 shrink-0 md:size-4\"\n style={{ color: `rgb(${rgb})`, opacity: item.status === 'pending' ? 0.4 : 1 }}\n />\n\n <span className=\"text-primary w-20 shrink-0 truncate text-[9px] md:w-28 md:text-xs\">\n {item.label}\n </span>\n\n <div\n role=\"progressbar\"\n aria-label={`${item.label} upload`}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={percent}\n className=\"bg-primary/10 h-1 min-w-0 flex-1 overflow-hidden rounded-full\"\n >\n <div\n className=\"h-full rounded-full transition-[width] duration-300\"\n style={{ width: `${String(percent)}%`, backgroundColor: `rgb(${rgb})` }}\n />\n </div>\n\n <span className=\"text-tertiary w-8 shrink-0 text-right text-[9px] tabular-nums md:text-xs\">\n {getUploadItemFilesDone(item)}/{item.fileSizes.length}\n </span>\n </li>\n );\n};\n\ninterface IUploadsBodyProps {\n title: string;\n description?: string;\n items: IUploadItem[];\n summary: IUploadsSummary;\n rgb: string;\n}\n\nconst UploadsBody = ({ title, description, items, summary, rgb }: IUploadsBodyProps) => (\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\" aria-live=\"polite\">\n <div className=\"flex flex-col gap-0.5\">\n <p className=\"line-clamp-1 text-xs font-semibold md:text-sm\" style={{ color: `rgb(${rgb})` }}>\n {uploadsHeading(title, summary, items.length)}\n </p>\n\n {description && (\n <p className=\"text-tertiary line-clamp-1 text-[9px]/3 md:text-xs\">{description}</p>\n )}\n\n <p className=\"text-tertiary text-[9px]/3 tabular-nums md:text-xs\">\n {uploadsSummaryText(summary)}\n </p>\n </div>\n\n {items.length > 1 && (\n <ul className=\"flex flex-col gap-1\">\n {items.map((item) => (\n <UploadRow key={item.id} item={item} />\n ))}\n </ul>\n )}\n </div>\n);\n\nconst cardConfig = (type: TToast['type']) => {\n switch (type) {\n case TOAST_TYPE.success:\n return { iconName: 'solar:check-circle-linear', rgb: GREEN_RGB };\n case TOAST_TYPE.error:\n return { iconName: 'solar:danger-triangle-linear', rgb: RED_RGB };\n case TOAST_TYPE.warning:\n return { iconName: 'solar:danger-triangle-linear', rgb: 'var(--primary-yellow-rgb)' };\n case TOAST_TYPE.progress:\n case TOAST_TYPE.uploads:\n return { iconName: '', rgb: 'var(--primary-rgb)' };\n case TOAST_TYPE.loading:\n return { iconName: 'beautinique:loading-spin', rgb: 'var(--primary-rgb)' };\n case TOAST_TYPE.default:\n case TOAST_TYPE.custom:\n default:\n return { iconName: 'solar:info-circle-outline', rgb: 'var(--primary-rgb)' };\n }\n};\n\nconst ToasterItem = (props: TToastItem & IClassName) => {\n const {\n className = '',\n type,\n icon,\n buttonProps,\n isClosable = true,\n autoClose = true,\n closeTimer = 5000,\n } = props;\n\n const remove = useToastStore((s) => s.remove);\n\n const [visible, setVisible] = useState(false);\n const [mounted, setMounted] = useState(true);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // An uploads toast stays while anything is still uploading, then closes by itself (later when\n // something failed, so it can be read).\n const uploadsSummary = props.type === TOAST_TYPE.uploads ? getUploadsSummary(props.items) : null;\n const isUploadsSettled = uploadsSummary?.isSettled ?? false;\n\n let resolvedAutoClose = autoClose;\n let resolvedIsClosable = isClosable;\n let resolvedCloseTimer = closeTimer;\n\n if (TOAST_TYPE.loading === type || TOAST_TYPE.progress === type) {\n resolvedAutoClose = false;\n resolvedIsClosable = false;\n } else if (uploadsSummary) {\n resolvedAutoClose = isUploadsSettled;\n resolvedIsClosable = isUploadsSettled;\n resolvedCloseTimer = uploadsSummary.failed > 0 ? 8000 : 2500;\n }\n\n const config = uploadsSummary\n ? { iconName: '', rgb: uploadsRgb(uploadsSummary) }\n : cardConfig(type);\n\n const handleClose = useCallback(() => {\n setVisible(false);\n\n timeoutRef.current = setTimeout(() => {\n setMounted(false);\n remove(props.id);\n }, 300);\n }, [remove, props.id]);\n\n useEffect(() => {\n const enterTimer = setTimeout(() => {\n setVisible(true);\n }, 50);\n\n let autoTimer: ReturnType<typeof setTimeout> | null = null;\n\n if (resolvedAutoClose) {\n autoTimer = setTimeout(() => {\n handleClose();\n }, resolvedCloseTimer);\n }\n\n return () => {\n clearTimeout(enterTimer);\n if (autoTimer) clearTimeout(autoTimer);\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, [resolvedAutoClose, resolvedCloseTimer, handleClose]);\n\n if (!mounted) return null;\n\n const isCustom = type === TOAST_TYPE.custom;\n\n return (\n <div\n className={`rounded-xl border-2 transition-all duration-300 ease-in-out ${\n visible ? 'translate-x-0 opacity-100' : 'translate-x-full opacity-0'\n } ${className}`}\n style={{\n borderColor: `rgba(${config.rgb}, 0.2)`,\n boxShadow: `0 10px 10px 0px rgba(${config.rgb}, 0.1)`,\n }}\n >\n <div className=\"bg-secondary-invert flex w-full items-center gap-2 rounded-[10.25px] p-1.5 md:p-2.5 lg:p-3 [&>svg]:size-5 [&>svg]:shrink-0 [&>svg]:md:size-6 [&>svg]:lg:size-7\">\n {icon ??\n (props.type === TOAST_TYPE.progress ? (\n <CircularProgress\n progress={props.progress}\n style={{ strokeColor: `rgb(${config.rgb})` }}\n />\n ) : uploadsSummary ? (\n <CircularProgress\n progress={uploadsSummary.percent}\n style={{ color: `rgb(${config.rgb})` }}\n />\n ) : (\n <Icon icon={config.iconName} style={{ color: `rgb(${config.rgb})` }} />\n ))}\n\n {props.type === TOAST_TYPE.uploads && uploadsSummary ? (\n <UploadsBody\n title={props.title}\n description={props.description}\n items={props.items}\n summary={uploadsSummary}\n rgb={config.rgb}\n />\n ) : (\n <div className=\"flex flex-1 items-center justify-between gap-2\">\n <div className=\"flex flex-col gap-0.5\">\n {!isCustom && 'title' in props && (\n <p\n className=\"line-clamp-1 text-xs font-semibold md:text-sm\"\n style={{ color: `rgb(${config.rgb})` }}\n >\n {props.title}\n </p>\n )}\n\n {!isCustom && 'description' in props && (\n <p className=\"text-tertiary line-clamp-2 text-[9px]/3 whitespace-pre-line md:text-xs\">\n {props.description}\n </p>\n )}\n {isCustom && 'children' in props && props.children}\n </div>\n\n {buttonProps && type !== TOAST_TYPE.loading && type !== TOAST_TYPE.progress && (\n <Button\n {...buttonProps}\n content={buttonProps.content ?? 'Try Again'}\n pattern={buttonProps.pattern ?? 'secondary'}\n className={`w-fit! rounded-md! px-2! py-1! pt-1.5! text-[10px] whitespace-nowrap md:text-xs! ${buttonProps.className ?? ''}`}\n />\n )}\n </div>\n )}\n\n {resolvedIsClosable && (\n <Icon\n icon=\"lucide:x\"\n className=\"text-primary cursor-pointer md:size-5\"\n onClick={handleClose}\n />\n )}\n </div>\n </div>\n );\n};\n\n/*\n * The store changes only the toast that was updated (the others keep the same object), and a toast\n * that is uploading is updated many times a second. With `memo` the toasts that did not change\n * are not rendered again for each of those updates.\n */\nexport const Toaster = memo(ToasterItem);\n\nexport const ToastContainer = () => {\n const toasts = useToastStore((s) => s.toasts);\n\n if (toasts.length === 0) return null;\n\n return (\n <div className=\"base:max-w-sm fixed right-2 bottom-2 z-999 flex w-full max-w-xs flex-col gap-2 sm:max-w-md md:right-4 md:bottom-4 md:max-w-lg lg:right-8 lg:bottom-8 lg:max-w-xl\">\n {toasts.map((toast) => (\n <Toaster key={toast.id} {...toast} id={toast.id} />\n ))}\n </div>\n );\n};\n"]}
|
package/dist/ui/Button.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.cts","sourceRoot":"","sources":["../../src/ui/Button.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Button.d.cts","sourceRoot":"","sources":["../../src/ui/Button.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAKrD,eAAO,MAAM,MAAM,GAAI,yEAQpB,OAAO,gCAaT,CAAC"}
|
package/dist/ui/Button.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/ui/Button.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/ui/Button.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAKrD,eAAO,MAAM,MAAM,GAAI,yEAQpB,OAAO,gCAaT,CAAC"}
|
package/dist/ui/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var react = require('@iconify/react');
|
|
4
|
-
var tailwindMerge = require('tailwind-merge');
|
|
5
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
5
|
var react$1 = require('react');
|
|
7
6
|
var reactDom = require('react-dom');
|
|
@@ -28,14 +27,14 @@ var Button = /* @__PURE__ */ __name(({
|
|
|
28
27
|
buttonProps,
|
|
29
28
|
ref
|
|
30
29
|
}) => (
|
|
31
|
-
//
|
|
32
|
-
//
|
|
30
|
+
// The classes that are given come last but do not remove the button's own: to win over one of
|
|
31
|
+
// them give it with `!` (`rounded-md!`), the way the toast's button does.
|
|
33
32
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
34
33
|
"button",
|
|
35
34
|
{
|
|
36
35
|
...buttonProps,
|
|
37
36
|
ref,
|
|
38
|
-
className:
|
|
37
|
+
className: `${BASE_CSS} ${getButtonCss(pattern)} ${className} ${buttonProps?.className ?? ""}`,
|
|
39
38
|
type: buttonProps?.type ?? "button",
|
|
40
39
|
children: [
|
|
41
40
|
leftIcon && /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { ...leftIcon }),
|
package/dist/ui/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/button.ts","../../src/ui/Button.tsx","../../src/lib/constants.ts","../../src/lib/tooltip.ts","../../src/ui/Tooltip.tsx"],"names":["jsxs","twMerge","jsx","Icon","useId","useRef","useState","useCallback","useEffect","useLayoutEffect","useMemo","isValidElement","cloneElement","createPortal"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { IButton } from '../types/component.js';\n\ntype TPattern = IButton['pattern'];\n\n// A `Record`: adding a pattern to the type is a type error here until it has a look.\nconst PATTERN_CSS: Record<TPattern, string> = {\n primary: 'text-white bg-sky-blue-burst shadow-primary-btn hover:shadow-primary-btn-hover',\n secondary:\n 'text-secondary-invert bg-secondary shadow-secondary-btn hover:shadow-secondary-btn-hover',\n tertiary: 'text-tertiary-invert bg-tertiary shadow-tertiary-btn hover:shadow-tertiary-btn-hover',\n outline: 'text-primary border border-primary shadow-outline-btn hover:shadow-outline-btn-hover',\n transparent: 'bg-transparent border border-primary/30 text-secondary',\n};\n\n/** The look of a pattern; a pattern nobody knows (from code that is not type checked) is transparent. */\nexport const getButtonCss = (pattern: TPattern) =>\n Object.hasOwn(PATTERN_CSS, pattern) ? PATTERN_CSS[pattern] : PATTERN_CSS.transparent;\n","import { Icon } from '@iconify/react';\nimport { twMerge } from 'tailwind-merge';\n\nimport { getButtonCss } from '../lib/button.js';\nimport type { IButton } from '../types/component.js';\n\nconst BASE_CSS =\n 'group flex w-full cursor-pointer items-center justify-center gap-1 rounded-lg px-4 py-3 text-sm leading-4 transition-all duration-300 disabled:cursor-not-allowed disabled:opacity-85 lg:px-5 lg:py-4 xl:text-base';\n\nexport const Button = ({\n pattern,\n content,\n className = '',\n leftIcon,\n rightIcon,\n buttonProps,\n ref,\n}: IButton) => (\n // A class that is given wins over the one it clashes with (`rounded-md` over `rounded-lg`),\n // with no `!`; one for another screen size (`lg:px-5`) is a different class and stays.\n <button\n {...buttonProps}\n ref={ref}\n className={twMerge(BASE_CSS, getButtonCss(pattern), className, buttonProps?.className)}\n type={buttonProps?.type ?? 'button'}\n >\n {leftIcon && <Icon {...leftIcon} />}\n {typeof content === 'object' ? <Icon {...content} /> : content}\n {rightIcon && <Icon {...rightIcon} />}\n </button>\n);\n","export const TOOLTIP_GAP = 15 as const;\nexport const TOOLTIP_ANIMATION_DURATION = 400 as const;\n/** The least space a tooltip keeps between itself and the edge of the window. */\nexport const TOOLTIP_VIEWPORT_MARGIN = 8 as const;\n/** The arrow stays at least this far from the ends of the tooltip (its own size and the rounded corner). */\nexport const TOOLTIP_ARROW_INSET = 16 as const;\n\nexport const TOAST_TYPES = [\n 'success',\n 'error',\n 'warning',\n 'progress',\n 'uploads',\n 'loading',\n 'default',\n 'custom',\n] as const;\n\nexport const TOAST_TYPE = Object.fromEntries(TOAST_TYPES.map((type) => [type, type])) as {\n [K in (typeof TOAST_TYPES)[number]]: K;\n};\n","import type { ITooltip } from '../types/component.js';\nimport { TOOLTIP_ARROW_INSET, TOOLTIP_GAP, TOOLTIP_VIEWPORT_MARGIN } from './constants.js';\n\ntype TPlacement = NonNullable<ITooltip['placement']>;\n\nexport interface ISize {\n width: number;\n height: number;\n}\n\nexport interface ITooltipLayout {\n /** The side the tooltip really opens on: the opposite one when there is no room on the asked one. */\n placement: TPlacement;\n /** Where the tooltip points to, in the window (it is moved away from it by `getTooltipTransform`). */\n position: { top: number; left: number };\n /** How far the arrow moves along the tooltip to keep pointing at the content when the tooltip is pushed in. */\n arrowShift: number;\n}\n\nconst OPPOSITE: Record<TPlacement, TPlacement> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\nconst clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);\n\nexport const getTooltipPosition = (\n rect: DOMRect,\n placement: TPlacement,\n): { top: number; left: number } => {\n switch (placement) {\n case 'bottom':\n return { top: rect.bottom, left: rect.left + rect.width / 2 };\n case 'right':\n return { top: rect.top + rect.height / 2, left: rect.right };\n case 'left':\n return { top: rect.top + rect.height / 2, left: rect.left };\n case 'top':\n default:\n return { top: rect.top, left: rect.left + rect.width / 2 };\n }\n};\n\n/** Whether a tooltip of this size, on this side of the content, stays inside the window. */\nconst fitsOn = (rect: DOMRect, size: ISize, placement: TPlacement, viewport: ISize) => {\n switch (placement) {\n case 'bottom':\n return rect.bottom + TOOLTIP_GAP + size.height <= viewport.height - TOOLTIP_VIEWPORT_MARGIN;\n case 'right':\n return rect.right + TOOLTIP_GAP + size.width <= viewport.width - TOOLTIP_VIEWPORT_MARGIN;\n case 'left':\n return rect.left - TOOLTIP_GAP - size.width >= TOOLTIP_VIEWPORT_MARGIN;\n case 'top':\n default:\n return rect.top - TOOLTIP_GAP - size.height >= TOOLTIP_VIEWPORT_MARGIN;\n }\n};\n\n/**\n * Where the tooltip goes. Without its `size` (it is not on the page yet) it goes where it was asked\n * to. With it, it opens on the opposite side when the asked one has no room and the other has, and\n * it is pushed along that side to stay inside the window; the arrow keeps pointing at the content.\n */\nexport const getTooltipLayout = ({\n rect,\n placement,\n size,\n viewport,\n}: {\n rect: DOMRect;\n placement: TPlacement;\n size?: ISize;\n viewport: ISize;\n}): ITooltipLayout => {\n if (!size) return { placement, position: getTooltipPosition(rect, placement), arrowShift: 0 };\n\n const side =\n !fitsOn(rect, size, placement, viewport) && fitsOn(rect, size, OPPOSITE[placement], viewport)\n ? OPPOSITE[placement]\n : placement;\n const position = getTooltipPosition(rect, side);\n\n const isHorizontal = side === 'top' || side === 'bottom';\n const length = isHorizontal ? size.width : size.height;\n const limit = isHorizontal ? viewport.width : viewport.height;\n const start = (isHorizontal ? position.left : position.top) - length / 2;\n const min = TOOLTIP_VIEWPORT_MARGIN;\n const max = limit - TOOLTIP_VIEWPORT_MARGIN - length;\n // a tooltip bigger than the window cannot be pushed in, it is left where it is\n const shift = max < min ? 0 : clamp(start, min, max) - start;\n const reach = Math.max(0, length / 2 - TOOLTIP_ARROW_INSET);\n const arrowShift = clamp(-shift, -reach, reach);\n\n return {\n placement: side,\n position: isHorizontal\n ? { top: position.top, left: position.left + shift }\n : { top: position.top + shift, left: position.left },\n arrowShift: arrowShift === 0 ? 0 : arrowShift, // never -0\n };\n};\n\n/** Whether two layouts put the tooltip in the same place (so there is nothing to change). */\nexport const isSameTooltipLayout = (a: ITooltipLayout, b: ITooltipLayout) =>\n a.placement === b.placement &&\n a.arrowShift === b.arrowShift &&\n a.position.top === b.position.top &&\n a.position.left === b.position.left;\n\nexport const getTooltipTransform = (placement: TPlacement, isVisible: boolean) => {\n const gap = String(isVisible ? TOOLTIP_GAP : 0);\n\n switch (placement) {\n case 'bottom':\n return `translate(-50%, ${gap}px)`;\n case 'right':\n return `translate(${gap}px, -50%)`;\n case 'left':\n return `translate(calc(-100% - ${gap}px), -50%)`;\n case 'top':\n default:\n return `translate(-50%, calc(-100% - ${gap}px))`;\n }\n};\n\n// The arrow sits in the middle of its side plus `--tooltip-arrow-shift` (set by the tooltip).\nexport const getTooltipArrowCss = (placement: TPlacement) => {\n switch (placement) {\n case 'bottom':\n return 'after:bottom-full after:left-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:-translate-x-1/2 after:border-b-silver-jet-2';\n case 'right':\n return 'after:top-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:right-full after:-translate-y-1/2 after:border-r-silver-jet-2';\n case 'left':\n return 'after:top-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:left-full after:-translate-y-1/2 after:border-l-silver-jet-2';\n case 'top':\n default:\n return 'after:top-full after:left-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:-translate-x-1/2 after:border-t-silver-jet-2';\n }\n};\n","import {\n cloneElement,\n type CSSProperties,\n isValidElement,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { TOOLTIP_ANIMATION_DURATION } from '../lib/constants.js';\nimport {\n getTooltipArrowCss,\n getTooltipLayout,\n getTooltipTransform,\n isSameTooltipLayout,\n type ITooltipLayout,\n} from '../lib/tooltip.js';\nimport type { ITooltip } from '../types/component.js';\n\n/*\n * `required={false}` keeps the wrapper (as `display: contents`, so it takes no room) instead of\n * returning the content alone: the content then stays in the same place of the tree when `required`\n * changes, and keeps its state (an open select, a focused input) instead of being created again.\n */\nexport const Tooltip = ({\n title,\n description,\n children,\n className = '',\n containerClassName = '',\n placement = 'top',\n required = true,\n}: ITooltip) => {\n const id = useId();\n const containerRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [isVisible, setIsVisible] = useState(false);\n const [layout, setLayout] = useState<ITooltipLayout>();\n const closeTimerRef = useRef<number | undefined>(undefined);\n const animationFrameRef = useRef<number | undefined>(undefined);\n\n // Places the tooltip from where the content is now and, once the tooltip is on the page, from its\n // size too, so it can open on the other side or be pushed in when it would leave the window.\n const updateLayout = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const next = getTooltipLayout({\n rect: container.getBoundingClientRect(),\n placement,\n size: tooltipRef.current?.getBoundingClientRect(),\n viewport: { width: window.innerWidth, height: window.innerHeight },\n });\n\n // the same place again: no new state, so no render\n setLayout((current) => (current && isSameTooltipLayout(current, next) ? current : next));\n }, [placement]);\n\n const openTooltip = () => {\n if (!required) return;\n\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n\n updateLayout();\n setIsVisible(false);\n setIsOpen(true);\n // two frames, so the browser has drawn it hidden first and the fade has something to start from\n animationFrameRef.current = window.requestAnimationFrame(() => {\n animationFrameRef.current = window.requestAnimationFrame(() => {\n setIsVisible(true);\n });\n });\n };\n\n const closeTooltip = useCallback(() => {\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n // Without this, a close that was asked twice (the mouse leaves, then the focus does) leaves the\n // first timer running with nobody holding it: it closes a tooltip the mouse has come back to.\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n\n setIsVisible(false);\n closeTimerRef.current = window.setTimeout(() => {\n setIsOpen(false);\n }, TOOLTIP_ANIMATION_DURATION);\n }, []);\n\n useEffect(() => {\n return () => {\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n };\n }, []);\n\n // Escape closes it, as a person who cannot move the mouse away has no other way to (WCAG 1.4.13).\n useEffect(() => {\n if (!isOpen) return;\n\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') closeTooltip();\n };\n\n document.addEventListener('keydown', closeOnEscape);\n\n return () => {\n document.removeEventListener('keydown', closeOnEscape);\n };\n }, [isOpen, closeTooltip]);\n\n // Follows the content while the window is resized or scrolled: at most once a frame, however\n // many scroll events there are.\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n updateLayout();\n\n let frame: number | undefined;\n const scheduleUpdate = () => {\n if (frame) return;\n\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n updateLayout();\n });\n };\n\n window.addEventListener('resize', scheduleUpdate);\n window.addEventListener('scroll', scheduleUpdate, true);\n\n return () => {\n window.removeEventListener('resize', scheduleUpdate);\n window.removeEventListener('scroll', scheduleUpdate, true);\n if (frame) window.cancelAnimationFrame(frame);\n };\n }, [isOpen, updateLayout]);\n\n // While the tooltip is there, the content is described by it (read by a screen reader when the\n // content has the focus). `useMemo` keeps the element the same between the renders the tooltip\n // makes by itself, so the content is not rendered again for each of them.\n const trigger = useMemo(() => {\n if (!required || !isOpen || !isValidElement<{ 'aria-describedby'?: string }>(children)) {\n return children;\n }\n\n const describedBy = children.props['aria-describedby'];\n\n return cloneElement(children, {\n 'aria-describedby': describedBy ? `${describedBy} ${id}` : id,\n });\n }, [children, id, isOpen, required]);\n\n const isShown = required && isOpen && layout !== undefined;\n\n return (\n <div\n ref={containerRef}\n className={required ? `relative inline-flex ${containerClassName}` : 'contents'}\n onBlur={closeTooltip}\n onFocus={openTooltip}\n onMouseEnter={openTooltip}\n onMouseLeave={closeTooltip}\n >\n {/* Main Content */}\n {trigger}\n {/* Tooltip */}\n {isShown &&\n createPortal(\n <div\n ref={tooltipRef}\n id={id}\n role=\"tooltip\"\n className={`border-silver-jet-2 bg-platinum-jet fixed z-9999 flex flex-col items-center justify-center rounded-lg border px-3 py-2 text-center whitespace-nowrap backdrop-blur-md transition-all duration-400 ease-in-out after:absolute after:border-8 after:border-solid after:border-transparent after:content-[''] ${isVisible ? 'visible opacity-100' : 'invisible opacity-0'} ${getTooltipArrowCss(layout.placement)} ${className} `}\n style={\n {\n ...layout.position,\n '--tooltip-arrow-shift': `${String(layout.arrowShift)}px`,\n transform: getTooltipTransform(layout.placement, isVisible),\n } as CSSProperties\n }\n >\n <div className=\"text-primary text-xs font-medium\">{title}</div>\n {description && (\n <div className=\"text-tertiary text-[10px] font-light\">{description}</div>\n )}\n </div>,\n document.body,\n )}\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/button.ts","../../src/ui/Button.tsx","../../src/lib/constants.ts","../../src/lib/tooltip.ts","../../src/ui/Tooltip.tsx"],"names":["jsxs","jsx","Icon","useId","useRef","useState","useCallback","useEffect","useLayoutEffect","useMemo","isValidElement","cloneElement","createPortal"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { IButton } from '../types/component.js';\n\ntype TPattern = IButton['pattern'];\n\n// A `Record`: adding a pattern to the type is a type error here until it has a look.\nconst PATTERN_CSS: Record<TPattern, string> = {\n primary: 'text-white bg-sky-blue-burst shadow-primary-btn hover:shadow-primary-btn-hover',\n secondary:\n 'text-secondary-invert bg-secondary shadow-secondary-btn hover:shadow-secondary-btn-hover',\n tertiary: 'text-tertiary-invert bg-tertiary shadow-tertiary-btn hover:shadow-tertiary-btn-hover',\n outline: 'text-primary border border-primary shadow-outline-btn hover:shadow-outline-btn-hover',\n transparent: 'bg-transparent border border-primary/30 text-secondary',\n};\n\n/** The look of a pattern; a pattern nobody knows (from code that is not type checked) is transparent. */\nexport const getButtonCss = (pattern: TPattern) =>\n Object.hasOwn(PATTERN_CSS, pattern) ? PATTERN_CSS[pattern] : PATTERN_CSS.transparent;\n","import { Icon } from '@iconify/react';\n\nimport { getButtonCss } from '../lib/button.js';\nimport type { IButton } from '../types/component.js';\n\nconst BASE_CSS =\n 'group flex w-full cursor-pointer items-center justify-center gap-1 rounded-lg px-4 py-3 text-sm leading-4 transition-all duration-300 disabled:cursor-not-allowed disabled:opacity-85 lg:px-5 lg:py-4 xl:text-base';\n\nexport const Button = ({\n pattern,\n content,\n className = '',\n leftIcon,\n rightIcon,\n buttonProps,\n ref,\n}: IButton) => (\n // The classes that are given come last but do not remove the button's own: to win over one of\n // them give it with `!` (`rounded-md!`), the way the toast's button does.\n <button\n {...buttonProps}\n ref={ref}\n className={`${BASE_CSS} ${getButtonCss(pattern)} ${className} ${buttonProps?.className ?? ''}`}\n type={buttonProps?.type ?? 'button'}\n >\n {leftIcon && <Icon {...leftIcon} />}\n {typeof content === 'object' ? <Icon {...content} /> : content}\n {rightIcon && <Icon {...rightIcon} />}\n </button>\n);\n","export const TOOLTIP_GAP = 15 as const;\nexport const TOOLTIP_ANIMATION_DURATION = 400 as const;\n/** The least space a tooltip keeps between itself and the edge of the window. */\nexport const TOOLTIP_VIEWPORT_MARGIN = 8 as const;\n/** The arrow stays at least this far from the ends of the tooltip (its own size and the rounded corner). */\nexport const TOOLTIP_ARROW_INSET = 16 as const;\n\nexport const TOAST_TYPES = [\n 'success',\n 'error',\n 'warning',\n 'progress',\n 'uploads',\n 'loading',\n 'default',\n 'custom',\n] as const;\n\nexport const TOAST_TYPE = Object.fromEntries(TOAST_TYPES.map((type) => [type, type])) as {\n [K in (typeof TOAST_TYPES)[number]]: K;\n};\n","import type { ITooltip } from '../types/component.js';\nimport { TOOLTIP_ARROW_INSET, TOOLTIP_GAP, TOOLTIP_VIEWPORT_MARGIN } from './constants.js';\n\ntype TPlacement = NonNullable<ITooltip['placement']>;\n\nexport interface ISize {\n width: number;\n height: number;\n}\n\nexport interface ITooltipLayout {\n /** The side the tooltip really opens on: the opposite one when there is no room on the asked one. */\n placement: TPlacement;\n /** Where the tooltip points to, in the window (it is moved away from it by `getTooltipTransform`). */\n position: { top: number; left: number };\n /** How far the arrow moves along the tooltip to keep pointing at the content when the tooltip is pushed in. */\n arrowShift: number;\n}\n\nconst OPPOSITE: Record<TPlacement, TPlacement> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\nconst clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);\n\nexport const getTooltipPosition = (\n rect: DOMRect,\n placement: TPlacement,\n): { top: number; left: number } => {\n switch (placement) {\n case 'bottom':\n return { top: rect.bottom, left: rect.left + rect.width / 2 };\n case 'right':\n return { top: rect.top + rect.height / 2, left: rect.right };\n case 'left':\n return { top: rect.top + rect.height / 2, left: rect.left };\n case 'top':\n default:\n return { top: rect.top, left: rect.left + rect.width / 2 };\n }\n};\n\n/** Whether a tooltip of this size, on this side of the content, stays inside the window. */\nconst fitsOn = (rect: DOMRect, size: ISize, placement: TPlacement, viewport: ISize) => {\n switch (placement) {\n case 'bottom':\n return rect.bottom + TOOLTIP_GAP + size.height <= viewport.height - TOOLTIP_VIEWPORT_MARGIN;\n case 'right':\n return rect.right + TOOLTIP_GAP + size.width <= viewport.width - TOOLTIP_VIEWPORT_MARGIN;\n case 'left':\n return rect.left - TOOLTIP_GAP - size.width >= TOOLTIP_VIEWPORT_MARGIN;\n case 'top':\n default:\n return rect.top - TOOLTIP_GAP - size.height >= TOOLTIP_VIEWPORT_MARGIN;\n }\n};\n\n/**\n * Where the tooltip goes. Without its `size` (it is not on the page yet) it goes where it was asked\n * to. With it, it opens on the opposite side when the asked one has no room and the other has, and\n * it is pushed along that side to stay inside the window; the arrow keeps pointing at the content.\n */\nexport const getTooltipLayout = ({\n rect,\n placement,\n size,\n viewport,\n}: {\n rect: DOMRect;\n placement: TPlacement;\n size?: ISize;\n viewport: ISize;\n}): ITooltipLayout => {\n if (!size) return { placement, position: getTooltipPosition(rect, placement), arrowShift: 0 };\n\n const side =\n !fitsOn(rect, size, placement, viewport) && fitsOn(rect, size, OPPOSITE[placement], viewport)\n ? OPPOSITE[placement]\n : placement;\n const position = getTooltipPosition(rect, side);\n\n const isHorizontal = side === 'top' || side === 'bottom';\n const length = isHorizontal ? size.width : size.height;\n const limit = isHorizontal ? viewport.width : viewport.height;\n const start = (isHorizontal ? position.left : position.top) - length / 2;\n const min = TOOLTIP_VIEWPORT_MARGIN;\n const max = limit - TOOLTIP_VIEWPORT_MARGIN - length;\n // a tooltip bigger than the window cannot be pushed in, it is left where it is\n const shift = max < min ? 0 : clamp(start, min, max) - start;\n const reach = Math.max(0, length / 2 - TOOLTIP_ARROW_INSET);\n const arrowShift = clamp(-shift, -reach, reach);\n\n return {\n placement: side,\n position: isHorizontal\n ? { top: position.top, left: position.left + shift }\n : { top: position.top + shift, left: position.left },\n arrowShift: arrowShift === 0 ? 0 : arrowShift, // never -0\n };\n};\n\n/** Whether two layouts put the tooltip in the same place (so there is nothing to change). */\nexport const isSameTooltipLayout = (a: ITooltipLayout, b: ITooltipLayout) =>\n a.placement === b.placement &&\n a.arrowShift === b.arrowShift &&\n a.position.top === b.position.top &&\n a.position.left === b.position.left;\n\nexport const getTooltipTransform = (placement: TPlacement, isVisible: boolean) => {\n const gap = String(isVisible ? TOOLTIP_GAP : 0);\n\n switch (placement) {\n case 'bottom':\n return `translate(-50%, ${gap}px)`;\n case 'right':\n return `translate(${gap}px, -50%)`;\n case 'left':\n return `translate(calc(-100% - ${gap}px), -50%)`;\n case 'top':\n default:\n return `translate(-50%, calc(-100% - ${gap}px))`;\n }\n};\n\n// The arrow sits in the middle of its side plus `--tooltip-arrow-shift` (set by the tooltip).\nexport const getTooltipArrowCss = (placement: TPlacement) => {\n switch (placement) {\n case 'bottom':\n return 'after:bottom-full after:left-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:-translate-x-1/2 after:border-b-silver-jet-2';\n case 'right':\n return 'after:top-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:right-full after:-translate-y-1/2 after:border-r-silver-jet-2';\n case 'left':\n return 'after:top-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:left-full after:-translate-y-1/2 after:border-l-silver-jet-2';\n case 'top':\n default:\n return 'after:top-full after:left-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:-translate-x-1/2 after:border-t-silver-jet-2';\n }\n};\n","import {\n cloneElement,\n type CSSProperties,\n isValidElement,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { TOOLTIP_ANIMATION_DURATION } from '../lib/constants.js';\nimport {\n getTooltipArrowCss,\n getTooltipLayout,\n getTooltipTransform,\n isSameTooltipLayout,\n type ITooltipLayout,\n} from '../lib/tooltip.js';\nimport type { ITooltip } from '../types/component.js';\n\n/*\n * `required={false}` keeps the wrapper (as `display: contents`, so it takes no room) instead of\n * returning the content alone: the content then stays in the same place of the tree when `required`\n * changes, and keeps its state (an open select, a focused input) instead of being created again.\n */\nexport const Tooltip = ({\n title,\n description,\n children,\n className = '',\n containerClassName = '',\n placement = 'top',\n required = true,\n}: ITooltip) => {\n const id = useId();\n const containerRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [isVisible, setIsVisible] = useState(false);\n const [layout, setLayout] = useState<ITooltipLayout>();\n const closeTimerRef = useRef<number | undefined>(undefined);\n const animationFrameRef = useRef<number | undefined>(undefined);\n\n // Places the tooltip from where the content is now and, once the tooltip is on the page, from its\n // size too, so it can open on the other side or be pushed in when it would leave the window.\n const updateLayout = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const next = getTooltipLayout({\n rect: container.getBoundingClientRect(),\n placement,\n size: tooltipRef.current?.getBoundingClientRect(),\n viewport: { width: window.innerWidth, height: window.innerHeight },\n });\n\n // the same place again: no new state, so no render\n setLayout((current) => (current && isSameTooltipLayout(current, next) ? current : next));\n }, [placement]);\n\n const openTooltip = () => {\n if (!required) return;\n\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n\n updateLayout();\n setIsVisible(false);\n setIsOpen(true);\n // two frames, so the browser has drawn it hidden first and the fade has something to start from\n animationFrameRef.current = window.requestAnimationFrame(() => {\n animationFrameRef.current = window.requestAnimationFrame(() => {\n setIsVisible(true);\n });\n });\n };\n\n const closeTooltip = useCallback(() => {\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n // Without this, a close that was asked twice (the mouse leaves, then the focus does) leaves the\n // first timer running with nobody holding it: it closes a tooltip the mouse has come back to.\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n\n setIsVisible(false);\n closeTimerRef.current = window.setTimeout(() => {\n setIsOpen(false);\n }, TOOLTIP_ANIMATION_DURATION);\n }, []);\n\n useEffect(() => {\n return () => {\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n };\n }, []);\n\n // Escape closes it, as a person who cannot move the mouse away has no other way to (WCAG 1.4.13).\n useEffect(() => {\n if (!isOpen) return;\n\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') closeTooltip();\n };\n\n document.addEventListener('keydown', closeOnEscape);\n\n return () => {\n document.removeEventListener('keydown', closeOnEscape);\n };\n }, [isOpen, closeTooltip]);\n\n // Follows the content while the window is resized or scrolled: at most once a frame, however\n // many scroll events there are.\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n updateLayout();\n\n let frame: number | undefined;\n const scheduleUpdate = () => {\n if (frame) return;\n\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n updateLayout();\n });\n };\n\n window.addEventListener('resize', scheduleUpdate);\n window.addEventListener('scroll', scheduleUpdate, true);\n\n return () => {\n window.removeEventListener('resize', scheduleUpdate);\n window.removeEventListener('scroll', scheduleUpdate, true);\n if (frame) window.cancelAnimationFrame(frame);\n };\n }, [isOpen, updateLayout]);\n\n // While the tooltip is there, the content is described by it (read by a screen reader when the\n // content has the focus). `useMemo` keeps the element the same between the renders the tooltip\n // makes by itself, so the content is not rendered again for each of them.\n const trigger = useMemo(() => {\n if (!required || !isOpen || !isValidElement<{ 'aria-describedby'?: string }>(children)) {\n return children;\n }\n\n const describedBy = children.props['aria-describedby'];\n\n return cloneElement(children, {\n 'aria-describedby': describedBy ? `${describedBy} ${id}` : id,\n });\n }, [children, id, isOpen, required]);\n\n const isShown = required && isOpen && layout !== undefined;\n\n return (\n <div\n ref={containerRef}\n className={required ? `relative inline-flex ${containerClassName}` : 'contents'}\n onBlur={closeTooltip}\n onFocus={openTooltip}\n onMouseEnter={openTooltip}\n onMouseLeave={closeTooltip}\n >\n {/* Main Content */}\n {trigger}\n {/* Tooltip */}\n {isShown &&\n createPortal(\n <div\n ref={tooltipRef}\n id={id}\n role=\"tooltip\"\n className={`border-silver-jet-2 bg-platinum-jet fixed z-9999 flex flex-col items-center justify-center rounded-lg border px-3 py-2 text-center whitespace-nowrap backdrop-blur-md transition-all duration-400 ease-in-out after:absolute after:border-8 after:border-solid after:border-transparent after:content-[''] ${isVisible ? 'visible opacity-100' : 'invisible opacity-0'} ${getTooltipArrowCss(layout.placement)} ${className} `}\n style={\n {\n ...layout.position,\n '--tooltip-arrow-shift': `${String(layout.arrowShift)}px`,\n transform: getTooltipTransform(layout.placement, isVisible),\n } as CSSProperties\n }\n >\n <div className=\"text-primary text-xs font-medium\">{title}</div>\n {description && (\n <div className=\"text-tertiary text-[10px] font-light\">{description}</div>\n )}\n </div>,\n document.body,\n )}\n </div>\n );\n};\n"]}
|
package/dist/ui/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Icon } from '@iconify/react';
|
|
2
|
-
import { twMerge } from 'tailwind-merge';
|
|
3
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
3
|
import { useId, useRef, useState, useCallback, useEffect, useLayoutEffect, useMemo, isValidElement, cloneElement } from 'react';
|
|
5
4
|
import { createPortal } from 'react-dom';
|
|
@@ -26,14 +25,14 @@ var Button = /* @__PURE__ */ __name(({
|
|
|
26
25
|
buttonProps,
|
|
27
26
|
ref
|
|
28
27
|
}) => (
|
|
29
|
-
//
|
|
30
|
-
//
|
|
28
|
+
// The classes that are given come last but do not remove the button's own: to win over one of
|
|
29
|
+
// them give it with `!` (`rounded-md!`), the way the toast's button does.
|
|
31
30
|
/* @__PURE__ */ jsxs(
|
|
32
31
|
"button",
|
|
33
32
|
{
|
|
34
33
|
...buttonProps,
|
|
35
34
|
ref,
|
|
36
|
-
className:
|
|
35
|
+
className: `${BASE_CSS} ${getButtonCss(pattern)} ${className} ${buttonProps?.className ?? ""}`,
|
|
37
36
|
type: buttonProps?.type ?? "button",
|
|
38
37
|
children: [
|
|
39
38
|
leftIcon && /* @__PURE__ */ jsx(Icon, { ...leftIcon }),
|
package/dist/ui/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/button.ts","../../src/ui/Button.tsx","../../src/lib/constants.ts","../../src/lib/tooltip.ts","../../src/ui/Tooltip.tsx"],"names":["jsxs","jsx"],"mappings":";;;;;;;;;;AAKA,IAAM,WAAA,GAAwC;AAAA,EAC5C,OAAA,EAAS,gFAAA;AAAA,EACT,SAAA,EACE,0FAAA;AAAA,EACF,QAAA,EAAU,sFAAA;AAAA,EACV,OAAA,EAAS,sFAAA;AAAA,EACT,WAAA,EAAa;AACf,CAAA;AAGO,IAAM,YAAA,mBAAe,MAAA,CAAA,CAAC,OAAA,KAC3B,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa,OAAO,CAAA,GAAI,WAAA,CAAY,OAAO,CAAA,GAAI,WAAA,CAAY,WAAA,EAD/C,cAAA,CAAA;ACT5B,IAAM,QAAA,GACJ,oNAAA;AAEK,IAAM,yBAAS,MAAA,CAAA,CAAC;AAAA,EACrB,OAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA;AAAA;AAAA;AAAA,kBAGE,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACE,GAAG,WAAA;AAAA,MACJ,GAAA;AAAA,MACA,SAAA,EAAW,QAAQ,QAAA,EAAU,YAAA,CAAa,OAAO,CAAA,EAAG,SAAA,EAAW,aAAa,SAAS,CAAA;AAAA,MACrF,IAAA,EAAM,aAAa,IAAA,IAAQ,QAAA;AAAA,MAE1B,QAAA,EAAA;AAAA,QAAA,QAAA,oBAAY,GAAA,CAAC,IAAA,EAAA,EAAM,GAAG,QAAA,EAAU,CAAA;AAAA,QAChC,OAAO,OAAA,KAAY,QAAA,uBAAY,IAAA,EAAA,EAAM,GAAG,SAAS,CAAA,GAAK,OAAA;AAAA,QACtD,SAAA,oBAAa,GAAA,CAAC,IAAA,EAAA,EAAM,GAAG,SAAA,EAAW;AAAA;AAAA;AAAA;AACrC,CAAA,EApBoB,QAAA;;;ACTf,IAAM,WAAA,GAAc,EAAA;AACpB,IAAM,0BAAA,GAA6B,GAAA;AAEnC,IAAM,uBAAA,GAA0B,CAAA;AAEhC,IAAM,mBAAA,GAAsB,EAAA;AAE5B,IAAM,WAAA,GAAc;AAAA,EACzB,SAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA;AAE0B,MAAA,CAAO,WAAA,CAAY,WAAA,CAAY,GAAA,CAAI,CAAC,IAAA,KAAS,CAAC,IAAA,EAAM,IAAI,CAAC,CAAC;;;ACCpF,IAAM,QAAA,GAA2C;AAAA,EAC/C,GAAA,EAAK,QAAA;AAAA,EACL,MAAA,EAAQ,KAAA;AAAA,EACR,IAAA,EAAM,OAAA;AAAA,EACN,KAAA,EAAO;AACT,CAAA;AAEA,IAAM,KAAA,mBAAQ,MAAA,CAAA,CAAC,KAAA,EAAe,GAAA,EAAa,GAAA,KAAgB,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA,EAAG,GAAG,CAAA,EAA/E,OAAA,CAAA;AAEP,IAAM,kBAAA,mBAAqB,MAAA,CAAA,CAChC,IAAA,EACA,SAAA,KACkC;AAClC,EAAA,QAAQ,SAAA;AAAW,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,KAAK,IAAA,CAAK,MAAA,EAAQ,MAAM,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,KAAA,GAAQ,CAAA,EAAE;AAAA,IAC9D,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,KAAK,IAAA,CAAK,GAAA,GAAM,KAAK,MAAA,GAAS,CAAA,EAAG,IAAA,EAAM,IAAA,CAAK,KAAA,EAAM;AAAA,IAC7D,KAAK,MAAA;AACH,MAAA,OAAO,EAAE,KAAK,IAAA,CAAK,GAAA,GAAM,KAAK,MAAA,GAAS,CAAA,EAAG,IAAA,EAAM,IAAA,CAAK,IAAA,EAAK;AAAA,IAC5D,KAAK,KAAA;AAAA,IACL;AACE,MAAA,OAAO,EAAE,KAAK,IAAA,CAAK,GAAA,EAAK,MAAM,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,KAAA,GAAQ,CAAA,EAAE;AAAA;AAE/D,CAAA,EAfkC,oBAAA,CAAA;AAkBlC,IAAM,MAAA,mBAAS,MAAA,CAAA,CAAC,IAAA,EAAe,IAAA,EAAa,WAAuB,QAAA,KAAoB;AACrF,EAAA,QAAQ,SAAA;AAAW,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,KAAK,MAAA,GAAS,WAAA,GAAc,IAAA,CAAK,MAAA,IAAU,SAAS,MAAA,GAAS,uBAAA;AAAA,IACtE,KAAK,OAAA;AACH,MAAA,OAAO,KAAK,KAAA,GAAQ,WAAA,GAAc,IAAA,CAAK,KAAA,IAAS,SAAS,KAAA,GAAQ,uBAAA;AAAA,IACnE,KAAK,MAAA;AACH,MAAA,OAAO,IAAA,CAAK,IAAA,GAAO,WAAA,GAAc,IAAA,CAAK,KAAA,IAAS,uBAAA;AAAA,IACjD,KAAK,KAAA;AAAA,IACL;AACE,MAAA,OAAO,IAAA,CAAK,GAAA,GAAM,WAAA,GAAc,IAAA,CAAK,MAAA,IAAU,uBAAA;AAAA;AAErD,CAAA,EAZe,QAAA,CAAA;AAmBR,IAAM,mCAAmB,MAAA,CAAA,CAAC;AAAA,EAC/B,IAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAA,KAKsB;AACpB,EAAA,IAAI,CAAC,IAAA,EAAM,OAAO,EAAE,SAAA,EAAW,QAAA,EAAU,kBAAA,CAAmB,IAAA,EAAM,SAAS,CAAA,EAAG,UAAA,EAAY,CAAA,EAAE;AAE5F,EAAA,MAAM,OACJ,CAAC,MAAA,CAAO,MAAM,IAAA,EAAM,SAAA,EAAW,QAAQ,CAAA,IAAK,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,SAAS,SAAS,CAAA,EAAG,QAAQ,CAAA,GACxF,QAAA,CAAS,SAAS,CAAA,GAClB,SAAA;AACN,EAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,IAAA,EAAM,IAAI,CAAA;AAE9C,EAAA,MAAM,YAAA,GAAe,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,QAAA;AAChD,EAAA,MAAM,MAAA,GAAS,YAAA,GAAe,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,MAAA;AAChD,EAAA,MAAM,KAAA,GAAQ,YAAA,GAAe,QAAA,CAAS,KAAA,GAAQ,QAAA,CAAS,MAAA;AACvD,EAAA,MAAM,SAAS,YAAA,GAAe,QAAA,CAAS,IAAA,GAAO,QAAA,CAAS,OAAO,MAAA,GAAS,CAAA;AACvE,EAAA,MAAM,GAAA,GAAM,uBAAA;AACZ,EAAA,MAAM,GAAA,GAAM,QAAQ,uBAAA,GAA0B,MAAA;AAE9C,EAAA,MAAM,KAAA,GAAQ,MAAM,GAAA,GAAM,CAAA,GAAI,MAAM,KAAA,EAAO,GAAA,EAAK,GAAG,CAAA,GAAI,KAAA;AACvD,EAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAA,GAAS,IAAI,mBAAmB,CAAA;AAC1D,EAAA,MAAM,aAAa,KAAA,CAAM,CAAC,KAAA,EAAO,CAAC,OAAO,KAAK,CAAA;AAE9C,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,IAAA;AAAA,IACX,UAAU,YAAA,GACN,EAAE,KAAK,QAAA,CAAS,GAAA,EAAK,MAAM,QAAA,CAAS,IAAA,GAAO,KAAA,EAAM,GACjD,EAAE,GAAA,EAAK,QAAA,CAAS,MAAM,KAAA,EAAO,IAAA,EAAM,SAAS,IAAA,EAAK;AAAA,IACrD,UAAA,EAAY,UAAA,KAAe,CAAA,GAAI,CAAA,GAAI;AAAA;AAAA,GACrC;AACF,CAAA,EArCgC,kBAAA,CAAA;AAwCzB,IAAM,mBAAA,2BAAuB,CAAA,EAAmB,CAAA,KACrD,EAAE,SAAA,KAAc,CAAA,CAAE,SAAA,IAClB,CAAA,CAAE,UAAA,KAAe,CAAA,CAAE,cACnB,CAAA,CAAE,QAAA,CAAS,GAAA,KAAQ,CAAA,CAAE,QAAA,CAAS,GAAA,IAC9B,EAAE,QAAA,CAAS,IAAA,KAAS,CAAA,CAAE,QAAA,CAAS,IAAA,EAJE,qBAAA,CAAA;AAM5B,IAAM,mBAAA,mBAAsB,MAAA,CAAA,CAAC,SAAA,EAAuB,SAAA,KAAuB;AAChF,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,SAAA,GAAY,WAAA,GAAc,CAAC,CAAA;AAE9C,EAAA,QAAQ,SAAA;AAAW,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,mBAAmB,GAAG,CAAA,GAAA,CAAA;AAAA,IAC/B,KAAK,OAAA;AACH,MAAA,OAAO,aAAa,GAAG,CAAA,SAAA,CAAA;AAAA,IACzB,KAAK,MAAA;AACH,MAAA,OAAO,0BAA0B,GAAG,CAAA,UAAA,CAAA;AAAA,IACtC,KAAK,KAAA;AAAA,IACL;AACE,MAAA,OAAO,gCAAgC,GAAG,CAAA,IAAA,CAAA;AAAA;AAEhD,CAAA,EAdmC,qBAAA,CAAA;AAiB5B,IAAM,kBAAA,2BAAsB,SAAA,KAA0B;AAC3D,EAAA,QAAQ,SAAA;AAAW,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,8HAAA;AAAA,IACT,KAAK,OAAA;AACH,MAAA,OAAO,4HAAA;AAAA,IACT,KAAK,MAAA;AACH,MAAA,OAAO,2HAAA;AAAA,IACT,KAAK,KAAA;AAAA,IACL;AACE,MAAA,OAAO,2HAAA;AAAA;AAEb,CAAA,EAZkC,oBAAA,CAAA;ACnG3B,IAAM,0BAAU,MAAA,CAAA,CAAC;AAAA,EACtB,KAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,kBAAA,GAAqB,EAAA;AAAA,EACrB,SAAA,GAAY,KAAA;AAAA,EACZ,QAAA,GAAW;AACb,CAAA,KAAgB;AACd,EAAA,MAAM,KAAK,KAAA,EAAM;AACjB,EAAA,MAAM,YAAA,GAAe,OAAuB,IAAI,CAAA;AAChD,EAAA,MAAM,UAAA,GAAa,OAAuB,IAAI,CAAA;AAC9C,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAC1C,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,QAAA,EAAyB;AACrD,EAAA,MAAM,aAAA,GAAgB,OAA2B,MAAS,CAAA;AAC1D,EAAA,MAAM,iBAAA,GAAoB,OAA2B,MAAS,CAAA;AAI9D,EAAA,MAAM,YAAA,GAAe,YAAY,MAAM;AACrC,IAAA,MAAM,YAAY,YAAA,CAAa,OAAA;AAC/B,IAAA,IAAI,CAAC,SAAA,EAAW;AAEhB,IAAA,MAAM,OAAO,gBAAA,CAAiB;AAAA,MAC5B,IAAA,EAAM,UAAU,qBAAA,EAAsB;AAAA,MACtC,SAAA;AAAA,MACA,IAAA,EAAM,UAAA,CAAW,OAAA,EAAS,qBAAA,EAAsB;AAAA,MAChD,UAAU,EAAE,KAAA,EAAO,OAAO,UAAA,EAAY,MAAA,EAAQ,OAAO,WAAA;AAAY,KAClE,CAAA;AAGD,IAAA,SAAA,CAAU,CAAC,YAAa,OAAA,IAAW,mBAAA,CAAoB,SAAS,IAAI,CAAA,GAAI,UAAU,IAAK,CAAA;AAAA,EACzF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,8BAAc,MAAA,CAAA,MAAM;AACxB,IAAA,IAAI,CAAC,QAAA,EAAU;AAEf,IAAA,IAAI,aAAA,CAAc,OAAA,EAAS,MAAA,CAAO,YAAA,CAAa,cAAc,OAAO,CAAA;AACpE,IAAA,IAAI,iBAAA,CAAkB,OAAA,EAAS,MAAA,CAAO,oBAAA,CAAqB,kBAAkB,OAAO,CAAA;AAEpF,IAAA,YAAA,EAAa;AACb,IAAA,YAAA,CAAa,KAAK,CAAA;AAClB,IAAA,SAAA,CAAU,IAAI,CAAA;AAEd,IAAA,iBAAA,CAAkB,OAAA,GAAU,MAAA,CAAO,qBAAA,CAAsB,MAAM;AAC7D,MAAA,iBAAA,CAAkB,OAAA,GAAU,MAAA,CAAO,qBAAA,CAAsB,MAAM;AAC7D,QAAA,YAAA,CAAa,IAAI,CAAA;AAAA,MACnB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,CAAA,EAfoB,aAAA,CAAA;AAiBpB,EAAA,MAAM,YAAA,GAAe,YAAY,MAAM;AACrC,IAAA,IAAI,iBAAA,CAAkB,OAAA,EAAS,MAAA,CAAO,oBAAA,CAAqB,kBAAkB,OAAO,CAAA;AAGpF,IAAA,IAAI,aAAA,CAAc,OAAA,EAAS,MAAA,CAAO,YAAA,CAAa,cAAc,OAAO,CAAA;AAEpE,IAAA,YAAA,CAAa,KAAK,CAAA;AAClB,IAAA,aAAA,CAAc,OAAA,GAAU,MAAA,CAAO,UAAA,CAAW,MAAM;AAC9C,MAAA,SAAA,CAAU,KAAK,CAAA;AAAA,IACjB,GAAG,0BAA0B,CAAA;AAAA,EAC/B,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,aAAA,CAAc,OAAA,EAAS,MAAA,CAAO,YAAA,CAAa,cAAc,OAAO,CAAA;AACpE,MAAA,IAAI,iBAAA,CAAkB,OAAA,EAAS,MAAA,CAAO,oBAAA,CAAqB,kBAAkB,OAAO,CAAA;AAAA,IACtF,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,IAAA,MAAM,aAAA,2BAAiB,KAAA,KAAyB;AAC9C,MAAA,IAAI,KAAA,CAAM,GAAA,KAAQ,QAAA,EAAU,YAAA,EAAa;AAAA,IAC3C,CAAA,EAFsB,eAAA,CAAA;AAItB,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,aAAa,CAAA;AAElD,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,aAAa,CAAA;AAAA,IACvD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,YAAY,CAAC,CAAA;AAIzB,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,IAAA,YAAA,EAAa;AAEb,IAAA,IAAI,KAAA;AACJ,IAAA,MAAM,iCAAiB,MAAA,CAAA,MAAM;AAC3B,MAAA,IAAI,KAAA,EAAO;AAEX,MAAA,KAAA,GAAQ,MAAA,CAAO,sBAAsB,MAAM;AACzC,QAAA,KAAA,GAAQ,MAAA;AACR,QAAA,YAAA,EAAa;AAAA,MACf,CAAC,CAAA;AAAA,IACH,CAAA,EAPuB,gBAAA,CAAA;AASvB,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,cAAc,CAAA;AAChD,IAAA,MAAA,CAAO,gBAAA,CAAiB,QAAA,EAAU,cAAA,EAAgB,IAAI,CAAA;AAEtD,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,cAAc,CAAA;AACnD,MAAA,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,cAAA,EAAgB,IAAI,CAAA;AACzD,MAAA,IAAI,KAAA,EAAO,MAAA,CAAO,oBAAA,CAAqB,KAAK,CAAA;AAAA,IAC9C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,YAAY,CAAC,CAAA;AAKzB,EAAA,MAAM,OAAA,GAAU,QAAQ,MAAM;AAC5B,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,UAAU,CAAC,cAAA,CAAgD,QAAQ,CAAA,EAAG;AACtF,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,KAAA,CAAM,kBAAkB,CAAA;AAErD,IAAA,OAAO,aAAa,QAAA,EAAU;AAAA,MAC5B,oBAAoB,WAAA,GAAc,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,GAAK;AAAA,KAC5D,CAAA;AAAA,EACH,GAAG,CAAC,QAAA,EAAU,EAAA,EAAI,MAAA,EAAQ,QAAQ,CAAC,CAAA;AAEnC,EAAA,MAAM,OAAA,GAAU,QAAA,IAAY,MAAA,IAAU,MAAA,KAAW,MAAA;AAEjD,EAAA,uBACEA,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,YAAA;AAAA,MACL,SAAA,EAAW,QAAA,GAAW,CAAA,qBAAA,EAAwB,kBAAkB,CAAA,CAAA,GAAK,UAAA;AAAA,MACrE,MAAA,EAAQ,YAAA;AAAA,MACR,OAAA,EAAS,WAAA;AAAA,MACT,YAAA,EAAc,WAAA;AAAA,MACd,YAAA,EAAc,YAAA;AAAA,MAGb,QAAA,EAAA;AAAA,QAAA,OAAA;AAAA,QAEA,OAAA,IACC,YAAA;AAAA,0BACEA,IAAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,UAAA;AAAA,cACL,EAAA;AAAA,cACA,IAAA,EAAK,SAAA;AAAA,cACL,SAAA,EAAW,CAAA,2SAAA,EAA8S,SAAA,GAAY,qBAAA,GAAwB,qBAAqB,CAAA,CAAA,EAAI,kBAAA,CAAmB,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,CAAA;AAAA,cACva,KAAA,EACE;AAAA,gBACE,GAAG,MAAA,CAAO,QAAA;AAAA,gBACV,uBAAA,EAAyB,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,UAAU,CAAC,CAAA,EAAA,CAAA;AAAA,gBACrD,SAAA,EAAW,mBAAA,CAAoB,MAAA,CAAO,SAAA,EAAW,SAAS;AAAA,eAC5D;AAAA,cAGF,QAAA,EAAA;AAAA,gCAAAC,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kCAAA,EAAoC,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,gBACxD,+BACCA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wCAAwC,QAAA,EAAA,WAAA,EAAY;AAAA;AAAA;AAAA,WAEvE;AAAA,UACA,QAAA,CAAS;AAAA;AACX;AAAA;AAAA,GACJ;AAEJ,CAAA,EAtKuB,SAAA","file":"index.js","sourcesContent":["import type { IButton } from '../types/component.js';\n\ntype TPattern = IButton['pattern'];\n\n// A `Record`: adding a pattern to the type is a type error here until it has a look.\nconst PATTERN_CSS: Record<TPattern, string> = {\n primary: 'text-white bg-sky-blue-burst shadow-primary-btn hover:shadow-primary-btn-hover',\n secondary:\n 'text-secondary-invert bg-secondary shadow-secondary-btn hover:shadow-secondary-btn-hover',\n tertiary: 'text-tertiary-invert bg-tertiary shadow-tertiary-btn hover:shadow-tertiary-btn-hover',\n outline: 'text-primary border border-primary shadow-outline-btn hover:shadow-outline-btn-hover',\n transparent: 'bg-transparent border border-primary/30 text-secondary',\n};\n\n/** The look of a pattern; a pattern nobody knows (from code that is not type checked) is transparent. */\nexport const getButtonCss = (pattern: TPattern) =>\n Object.hasOwn(PATTERN_CSS, pattern) ? PATTERN_CSS[pattern] : PATTERN_CSS.transparent;\n","import { Icon } from '@iconify/react';\nimport { twMerge } from 'tailwind-merge';\n\nimport { getButtonCss } from '../lib/button.js';\nimport type { IButton } from '../types/component.js';\n\nconst BASE_CSS =\n 'group flex w-full cursor-pointer items-center justify-center gap-1 rounded-lg px-4 py-3 text-sm leading-4 transition-all duration-300 disabled:cursor-not-allowed disabled:opacity-85 lg:px-5 lg:py-4 xl:text-base';\n\nexport const Button = ({\n pattern,\n content,\n className = '',\n leftIcon,\n rightIcon,\n buttonProps,\n ref,\n}: IButton) => (\n // A class that is given wins over the one it clashes with (`rounded-md` over `rounded-lg`),\n // with no `!`; one for another screen size (`lg:px-5`) is a different class and stays.\n <button\n {...buttonProps}\n ref={ref}\n className={twMerge(BASE_CSS, getButtonCss(pattern), className, buttonProps?.className)}\n type={buttonProps?.type ?? 'button'}\n >\n {leftIcon && <Icon {...leftIcon} />}\n {typeof content === 'object' ? <Icon {...content} /> : content}\n {rightIcon && <Icon {...rightIcon} />}\n </button>\n);\n","export const TOOLTIP_GAP = 15 as const;\nexport const TOOLTIP_ANIMATION_DURATION = 400 as const;\n/** The least space a tooltip keeps between itself and the edge of the window. */\nexport const TOOLTIP_VIEWPORT_MARGIN = 8 as const;\n/** The arrow stays at least this far from the ends of the tooltip (its own size and the rounded corner). */\nexport const TOOLTIP_ARROW_INSET = 16 as const;\n\nexport const TOAST_TYPES = [\n 'success',\n 'error',\n 'warning',\n 'progress',\n 'uploads',\n 'loading',\n 'default',\n 'custom',\n] as const;\n\nexport const TOAST_TYPE = Object.fromEntries(TOAST_TYPES.map((type) => [type, type])) as {\n [K in (typeof TOAST_TYPES)[number]]: K;\n};\n","import type { ITooltip } from '../types/component.js';\nimport { TOOLTIP_ARROW_INSET, TOOLTIP_GAP, TOOLTIP_VIEWPORT_MARGIN } from './constants.js';\n\ntype TPlacement = NonNullable<ITooltip['placement']>;\n\nexport interface ISize {\n width: number;\n height: number;\n}\n\nexport interface ITooltipLayout {\n /** The side the tooltip really opens on: the opposite one when there is no room on the asked one. */\n placement: TPlacement;\n /** Where the tooltip points to, in the window (it is moved away from it by `getTooltipTransform`). */\n position: { top: number; left: number };\n /** How far the arrow moves along the tooltip to keep pointing at the content when the tooltip is pushed in. */\n arrowShift: number;\n}\n\nconst OPPOSITE: Record<TPlacement, TPlacement> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\nconst clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);\n\nexport const getTooltipPosition = (\n rect: DOMRect,\n placement: TPlacement,\n): { top: number; left: number } => {\n switch (placement) {\n case 'bottom':\n return { top: rect.bottom, left: rect.left + rect.width / 2 };\n case 'right':\n return { top: rect.top + rect.height / 2, left: rect.right };\n case 'left':\n return { top: rect.top + rect.height / 2, left: rect.left };\n case 'top':\n default:\n return { top: rect.top, left: rect.left + rect.width / 2 };\n }\n};\n\n/** Whether a tooltip of this size, on this side of the content, stays inside the window. */\nconst fitsOn = (rect: DOMRect, size: ISize, placement: TPlacement, viewport: ISize) => {\n switch (placement) {\n case 'bottom':\n return rect.bottom + TOOLTIP_GAP + size.height <= viewport.height - TOOLTIP_VIEWPORT_MARGIN;\n case 'right':\n return rect.right + TOOLTIP_GAP + size.width <= viewport.width - TOOLTIP_VIEWPORT_MARGIN;\n case 'left':\n return rect.left - TOOLTIP_GAP - size.width >= TOOLTIP_VIEWPORT_MARGIN;\n case 'top':\n default:\n return rect.top - TOOLTIP_GAP - size.height >= TOOLTIP_VIEWPORT_MARGIN;\n }\n};\n\n/**\n * Where the tooltip goes. Without its `size` (it is not on the page yet) it goes where it was asked\n * to. With it, it opens on the opposite side when the asked one has no room and the other has, and\n * it is pushed along that side to stay inside the window; the arrow keeps pointing at the content.\n */\nexport const getTooltipLayout = ({\n rect,\n placement,\n size,\n viewport,\n}: {\n rect: DOMRect;\n placement: TPlacement;\n size?: ISize;\n viewport: ISize;\n}): ITooltipLayout => {\n if (!size) return { placement, position: getTooltipPosition(rect, placement), arrowShift: 0 };\n\n const side =\n !fitsOn(rect, size, placement, viewport) && fitsOn(rect, size, OPPOSITE[placement], viewport)\n ? OPPOSITE[placement]\n : placement;\n const position = getTooltipPosition(rect, side);\n\n const isHorizontal = side === 'top' || side === 'bottom';\n const length = isHorizontal ? size.width : size.height;\n const limit = isHorizontal ? viewport.width : viewport.height;\n const start = (isHorizontal ? position.left : position.top) - length / 2;\n const min = TOOLTIP_VIEWPORT_MARGIN;\n const max = limit - TOOLTIP_VIEWPORT_MARGIN - length;\n // a tooltip bigger than the window cannot be pushed in, it is left where it is\n const shift = max < min ? 0 : clamp(start, min, max) - start;\n const reach = Math.max(0, length / 2 - TOOLTIP_ARROW_INSET);\n const arrowShift = clamp(-shift, -reach, reach);\n\n return {\n placement: side,\n position: isHorizontal\n ? { top: position.top, left: position.left + shift }\n : { top: position.top + shift, left: position.left },\n arrowShift: arrowShift === 0 ? 0 : arrowShift, // never -0\n };\n};\n\n/** Whether two layouts put the tooltip in the same place (so there is nothing to change). */\nexport const isSameTooltipLayout = (a: ITooltipLayout, b: ITooltipLayout) =>\n a.placement === b.placement &&\n a.arrowShift === b.arrowShift &&\n a.position.top === b.position.top &&\n a.position.left === b.position.left;\n\nexport const getTooltipTransform = (placement: TPlacement, isVisible: boolean) => {\n const gap = String(isVisible ? TOOLTIP_GAP : 0);\n\n switch (placement) {\n case 'bottom':\n return `translate(-50%, ${gap}px)`;\n case 'right':\n return `translate(${gap}px, -50%)`;\n case 'left':\n return `translate(calc(-100% - ${gap}px), -50%)`;\n case 'top':\n default:\n return `translate(-50%, calc(-100% - ${gap}px))`;\n }\n};\n\n// The arrow sits in the middle of its side plus `--tooltip-arrow-shift` (set by the tooltip).\nexport const getTooltipArrowCss = (placement: TPlacement) => {\n switch (placement) {\n case 'bottom':\n return 'after:bottom-full after:left-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:-translate-x-1/2 after:border-b-silver-jet-2';\n case 'right':\n return 'after:top-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:right-full after:-translate-y-1/2 after:border-r-silver-jet-2';\n case 'left':\n return 'after:top-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:left-full after:-translate-y-1/2 after:border-l-silver-jet-2';\n case 'top':\n default:\n return 'after:top-full after:left-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:-translate-x-1/2 after:border-t-silver-jet-2';\n }\n};\n","import {\n cloneElement,\n type CSSProperties,\n isValidElement,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { TOOLTIP_ANIMATION_DURATION } from '../lib/constants.js';\nimport {\n getTooltipArrowCss,\n getTooltipLayout,\n getTooltipTransform,\n isSameTooltipLayout,\n type ITooltipLayout,\n} from '../lib/tooltip.js';\nimport type { ITooltip } from '../types/component.js';\n\n/*\n * `required={false}` keeps the wrapper (as `display: contents`, so it takes no room) instead of\n * returning the content alone: the content then stays in the same place of the tree when `required`\n * changes, and keeps its state (an open select, a focused input) instead of being created again.\n */\nexport const Tooltip = ({\n title,\n description,\n children,\n className = '',\n containerClassName = '',\n placement = 'top',\n required = true,\n}: ITooltip) => {\n const id = useId();\n const containerRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [isVisible, setIsVisible] = useState(false);\n const [layout, setLayout] = useState<ITooltipLayout>();\n const closeTimerRef = useRef<number | undefined>(undefined);\n const animationFrameRef = useRef<number | undefined>(undefined);\n\n // Places the tooltip from where the content is now and, once the tooltip is on the page, from its\n // size too, so it can open on the other side or be pushed in when it would leave the window.\n const updateLayout = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const next = getTooltipLayout({\n rect: container.getBoundingClientRect(),\n placement,\n size: tooltipRef.current?.getBoundingClientRect(),\n viewport: { width: window.innerWidth, height: window.innerHeight },\n });\n\n // the same place again: no new state, so no render\n setLayout((current) => (current && isSameTooltipLayout(current, next) ? current : next));\n }, [placement]);\n\n const openTooltip = () => {\n if (!required) return;\n\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n\n updateLayout();\n setIsVisible(false);\n setIsOpen(true);\n // two frames, so the browser has drawn it hidden first and the fade has something to start from\n animationFrameRef.current = window.requestAnimationFrame(() => {\n animationFrameRef.current = window.requestAnimationFrame(() => {\n setIsVisible(true);\n });\n });\n };\n\n const closeTooltip = useCallback(() => {\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n // Without this, a close that was asked twice (the mouse leaves, then the focus does) leaves the\n // first timer running with nobody holding it: it closes a tooltip the mouse has come back to.\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n\n setIsVisible(false);\n closeTimerRef.current = window.setTimeout(() => {\n setIsOpen(false);\n }, TOOLTIP_ANIMATION_DURATION);\n }, []);\n\n useEffect(() => {\n return () => {\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n };\n }, []);\n\n // Escape closes it, as a person who cannot move the mouse away has no other way to (WCAG 1.4.13).\n useEffect(() => {\n if (!isOpen) return;\n\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') closeTooltip();\n };\n\n document.addEventListener('keydown', closeOnEscape);\n\n return () => {\n document.removeEventListener('keydown', closeOnEscape);\n };\n }, [isOpen, closeTooltip]);\n\n // Follows the content while the window is resized or scrolled: at most once a frame, however\n // many scroll events there are.\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n updateLayout();\n\n let frame: number | undefined;\n const scheduleUpdate = () => {\n if (frame) return;\n\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n updateLayout();\n });\n };\n\n window.addEventListener('resize', scheduleUpdate);\n window.addEventListener('scroll', scheduleUpdate, true);\n\n return () => {\n window.removeEventListener('resize', scheduleUpdate);\n window.removeEventListener('scroll', scheduleUpdate, true);\n if (frame) window.cancelAnimationFrame(frame);\n };\n }, [isOpen, updateLayout]);\n\n // While the tooltip is there, the content is described by it (read by a screen reader when the\n // content has the focus). `useMemo` keeps the element the same between the renders the tooltip\n // makes by itself, so the content is not rendered again for each of them.\n const trigger = useMemo(() => {\n if (!required || !isOpen || !isValidElement<{ 'aria-describedby'?: string }>(children)) {\n return children;\n }\n\n const describedBy = children.props['aria-describedby'];\n\n return cloneElement(children, {\n 'aria-describedby': describedBy ? `${describedBy} ${id}` : id,\n });\n }, [children, id, isOpen, required]);\n\n const isShown = required && isOpen && layout !== undefined;\n\n return (\n <div\n ref={containerRef}\n className={required ? `relative inline-flex ${containerClassName}` : 'contents'}\n onBlur={closeTooltip}\n onFocus={openTooltip}\n onMouseEnter={openTooltip}\n onMouseLeave={closeTooltip}\n >\n {/* Main Content */}\n {trigger}\n {/* Tooltip */}\n {isShown &&\n createPortal(\n <div\n ref={tooltipRef}\n id={id}\n role=\"tooltip\"\n className={`border-silver-jet-2 bg-platinum-jet fixed z-9999 flex flex-col items-center justify-center rounded-lg border px-3 py-2 text-center whitespace-nowrap backdrop-blur-md transition-all duration-400 ease-in-out after:absolute after:border-8 after:border-solid after:border-transparent after:content-[''] ${isVisible ? 'visible opacity-100' : 'invisible opacity-0'} ${getTooltipArrowCss(layout.placement)} ${className} `}\n style={\n {\n ...layout.position,\n '--tooltip-arrow-shift': `${String(layout.arrowShift)}px`,\n transform: getTooltipTransform(layout.placement, isVisible),\n } as CSSProperties\n }\n >\n <div className=\"text-primary text-xs font-medium\">{title}</div>\n {description && (\n <div className=\"text-tertiary text-[10px] font-light\">{description}</div>\n )}\n </div>,\n document.body,\n )}\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/button.ts","../../src/ui/Button.tsx","../../src/lib/constants.ts","../../src/lib/tooltip.ts","../../src/ui/Tooltip.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import type { IButton } from '../types/component.js';\n\ntype TPattern = IButton['pattern'];\n\n// A `Record`: adding a pattern to the type is a type error here until it has a look.\nconst PATTERN_CSS: Record<TPattern, string> = {\n primary: 'text-white bg-sky-blue-burst shadow-primary-btn hover:shadow-primary-btn-hover',\n secondary:\n 'text-secondary-invert bg-secondary shadow-secondary-btn hover:shadow-secondary-btn-hover',\n tertiary: 'text-tertiary-invert bg-tertiary shadow-tertiary-btn hover:shadow-tertiary-btn-hover',\n outline: 'text-primary border border-primary shadow-outline-btn hover:shadow-outline-btn-hover',\n transparent: 'bg-transparent border border-primary/30 text-secondary',\n};\n\n/** The look of a pattern; a pattern nobody knows (from code that is not type checked) is transparent. */\nexport const getButtonCss = (pattern: TPattern) =>\n Object.hasOwn(PATTERN_CSS, pattern) ? PATTERN_CSS[pattern] : PATTERN_CSS.transparent;\n","import { Icon } from '@iconify/react';\n\nimport { getButtonCss } from '../lib/button.js';\nimport type { IButton } from '../types/component.js';\n\nconst BASE_CSS =\n 'group flex w-full cursor-pointer items-center justify-center gap-1 rounded-lg px-4 py-3 text-sm leading-4 transition-all duration-300 disabled:cursor-not-allowed disabled:opacity-85 lg:px-5 lg:py-4 xl:text-base';\n\nexport const Button = ({\n pattern,\n content,\n className = '',\n leftIcon,\n rightIcon,\n buttonProps,\n ref,\n}: IButton) => (\n // The classes that are given come last but do not remove the button's own: to win over one of\n // them give it with `!` (`rounded-md!`), the way the toast's button does.\n <button\n {...buttonProps}\n ref={ref}\n className={`${BASE_CSS} ${getButtonCss(pattern)} ${className} ${buttonProps?.className ?? ''}`}\n type={buttonProps?.type ?? 'button'}\n >\n {leftIcon && <Icon {...leftIcon} />}\n {typeof content === 'object' ? <Icon {...content} /> : content}\n {rightIcon && <Icon {...rightIcon} />}\n </button>\n);\n","export const TOOLTIP_GAP = 15 as const;\nexport const TOOLTIP_ANIMATION_DURATION = 400 as const;\n/** The least space a tooltip keeps between itself and the edge of the window. */\nexport const TOOLTIP_VIEWPORT_MARGIN = 8 as const;\n/** The arrow stays at least this far from the ends of the tooltip (its own size and the rounded corner). */\nexport const TOOLTIP_ARROW_INSET = 16 as const;\n\nexport const TOAST_TYPES = [\n 'success',\n 'error',\n 'warning',\n 'progress',\n 'uploads',\n 'loading',\n 'default',\n 'custom',\n] as const;\n\nexport const TOAST_TYPE = Object.fromEntries(TOAST_TYPES.map((type) => [type, type])) as {\n [K in (typeof TOAST_TYPES)[number]]: K;\n};\n","import type { ITooltip } from '../types/component.js';\nimport { TOOLTIP_ARROW_INSET, TOOLTIP_GAP, TOOLTIP_VIEWPORT_MARGIN } from './constants.js';\n\ntype TPlacement = NonNullable<ITooltip['placement']>;\n\nexport interface ISize {\n width: number;\n height: number;\n}\n\nexport interface ITooltipLayout {\n /** The side the tooltip really opens on: the opposite one when there is no room on the asked one. */\n placement: TPlacement;\n /** Where the tooltip points to, in the window (it is moved away from it by `getTooltipTransform`). */\n position: { top: number; left: number };\n /** How far the arrow moves along the tooltip to keep pointing at the content when the tooltip is pushed in. */\n arrowShift: number;\n}\n\nconst OPPOSITE: Record<TPlacement, TPlacement> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\nconst clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);\n\nexport const getTooltipPosition = (\n rect: DOMRect,\n placement: TPlacement,\n): { top: number; left: number } => {\n switch (placement) {\n case 'bottom':\n return { top: rect.bottom, left: rect.left + rect.width / 2 };\n case 'right':\n return { top: rect.top + rect.height / 2, left: rect.right };\n case 'left':\n return { top: rect.top + rect.height / 2, left: rect.left };\n case 'top':\n default:\n return { top: rect.top, left: rect.left + rect.width / 2 };\n }\n};\n\n/** Whether a tooltip of this size, on this side of the content, stays inside the window. */\nconst fitsOn = (rect: DOMRect, size: ISize, placement: TPlacement, viewport: ISize) => {\n switch (placement) {\n case 'bottom':\n return rect.bottom + TOOLTIP_GAP + size.height <= viewport.height - TOOLTIP_VIEWPORT_MARGIN;\n case 'right':\n return rect.right + TOOLTIP_GAP + size.width <= viewport.width - TOOLTIP_VIEWPORT_MARGIN;\n case 'left':\n return rect.left - TOOLTIP_GAP - size.width >= TOOLTIP_VIEWPORT_MARGIN;\n case 'top':\n default:\n return rect.top - TOOLTIP_GAP - size.height >= TOOLTIP_VIEWPORT_MARGIN;\n }\n};\n\n/**\n * Where the tooltip goes. Without its `size` (it is not on the page yet) it goes where it was asked\n * to. With it, it opens on the opposite side when the asked one has no room and the other has, and\n * it is pushed along that side to stay inside the window; the arrow keeps pointing at the content.\n */\nexport const getTooltipLayout = ({\n rect,\n placement,\n size,\n viewport,\n}: {\n rect: DOMRect;\n placement: TPlacement;\n size?: ISize;\n viewport: ISize;\n}): ITooltipLayout => {\n if (!size) return { placement, position: getTooltipPosition(rect, placement), arrowShift: 0 };\n\n const side =\n !fitsOn(rect, size, placement, viewport) && fitsOn(rect, size, OPPOSITE[placement], viewport)\n ? OPPOSITE[placement]\n : placement;\n const position = getTooltipPosition(rect, side);\n\n const isHorizontal = side === 'top' || side === 'bottom';\n const length = isHorizontal ? size.width : size.height;\n const limit = isHorizontal ? viewport.width : viewport.height;\n const start = (isHorizontal ? position.left : position.top) - length / 2;\n const min = TOOLTIP_VIEWPORT_MARGIN;\n const max = limit - TOOLTIP_VIEWPORT_MARGIN - length;\n // a tooltip bigger than the window cannot be pushed in, it is left where it is\n const shift = max < min ? 0 : clamp(start, min, max) - start;\n const reach = Math.max(0, length / 2 - TOOLTIP_ARROW_INSET);\n const arrowShift = clamp(-shift, -reach, reach);\n\n return {\n placement: side,\n position: isHorizontal\n ? { top: position.top, left: position.left + shift }\n : { top: position.top + shift, left: position.left },\n arrowShift: arrowShift === 0 ? 0 : arrowShift, // never -0\n };\n};\n\n/** Whether two layouts put the tooltip in the same place (so there is nothing to change). */\nexport const isSameTooltipLayout = (a: ITooltipLayout, b: ITooltipLayout) =>\n a.placement === b.placement &&\n a.arrowShift === b.arrowShift &&\n a.position.top === b.position.top &&\n a.position.left === b.position.left;\n\nexport const getTooltipTransform = (placement: TPlacement, isVisible: boolean) => {\n const gap = String(isVisible ? TOOLTIP_GAP : 0);\n\n switch (placement) {\n case 'bottom':\n return `translate(-50%, ${gap}px)`;\n case 'right':\n return `translate(${gap}px, -50%)`;\n case 'left':\n return `translate(calc(-100% - ${gap}px), -50%)`;\n case 'top':\n default:\n return `translate(-50%, calc(-100% - ${gap}px))`;\n }\n};\n\n// The arrow sits in the middle of its side plus `--tooltip-arrow-shift` (set by the tooltip).\nexport const getTooltipArrowCss = (placement: TPlacement) => {\n switch (placement) {\n case 'bottom':\n return 'after:bottom-full after:left-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:-translate-x-1/2 after:border-b-silver-jet-2';\n case 'right':\n return 'after:top-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:right-full after:-translate-y-1/2 after:border-r-silver-jet-2';\n case 'left':\n return 'after:top-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:left-full after:-translate-y-1/2 after:border-l-silver-jet-2';\n case 'top':\n default:\n return 'after:top-full after:left-[calc(50%_+_var(--tooltip-arrow-shift,0px))] after:-translate-x-1/2 after:border-t-silver-jet-2';\n }\n};\n","import {\n cloneElement,\n type CSSProperties,\n isValidElement,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { TOOLTIP_ANIMATION_DURATION } from '../lib/constants.js';\nimport {\n getTooltipArrowCss,\n getTooltipLayout,\n getTooltipTransform,\n isSameTooltipLayout,\n type ITooltipLayout,\n} from '../lib/tooltip.js';\nimport type { ITooltip } from '../types/component.js';\n\n/*\n * `required={false}` keeps the wrapper (as `display: contents`, so it takes no room) instead of\n * returning the content alone: the content then stays in the same place of the tree when `required`\n * changes, and keeps its state (an open select, a focused input) instead of being created again.\n */\nexport const Tooltip = ({\n title,\n description,\n children,\n className = '',\n containerClassName = '',\n placement = 'top',\n required = true,\n}: ITooltip) => {\n const id = useId();\n const containerRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [isVisible, setIsVisible] = useState(false);\n const [layout, setLayout] = useState<ITooltipLayout>();\n const closeTimerRef = useRef<number | undefined>(undefined);\n const animationFrameRef = useRef<number | undefined>(undefined);\n\n // Places the tooltip from where the content is now and, once the tooltip is on the page, from its\n // size too, so it can open on the other side or be pushed in when it would leave the window.\n const updateLayout = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const next = getTooltipLayout({\n rect: container.getBoundingClientRect(),\n placement,\n size: tooltipRef.current?.getBoundingClientRect(),\n viewport: { width: window.innerWidth, height: window.innerHeight },\n });\n\n // the same place again: no new state, so no render\n setLayout((current) => (current && isSameTooltipLayout(current, next) ? current : next));\n }, [placement]);\n\n const openTooltip = () => {\n if (!required) return;\n\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n\n updateLayout();\n setIsVisible(false);\n setIsOpen(true);\n // two frames, so the browser has drawn it hidden first and the fade has something to start from\n animationFrameRef.current = window.requestAnimationFrame(() => {\n animationFrameRef.current = window.requestAnimationFrame(() => {\n setIsVisible(true);\n });\n });\n };\n\n const closeTooltip = useCallback(() => {\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n // Without this, a close that was asked twice (the mouse leaves, then the focus does) leaves the\n // first timer running with nobody holding it: it closes a tooltip the mouse has come back to.\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n\n setIsVisible(false);\n closeTimerRef.current = window.setTimeout(() => {\n setIsOpen(false);\n }, TOOLTIP_ANIMATION_DURATION);\n }, []);\n\n useEffect(() => {\n return () => {\n if (closeTimerRef.current) window.clearTimeout(closeTimerRef.current);\n if (animationFrameRef.current) window.cancelAnimationFrame(animationFrameRef.current);\n };\n }, []);\n\n // Escape closes it, as a person who cannot move the mouse away has no other way to (WCAG 1.4.13).\n useEffect(() => {\n if (!isOpen) return;\n\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') closeTooltip();\n };\n\n document.addEventListener('keydown', closeOnEscape);\n\n return () => {\n document.removeEventListener('keydown', closeOnEscape);\n };\n }, [isOpen, closeTooltip]);\n\n // Follows the content while the window is resized or scrolled: at most once a frame, however\n // many scroll events there are.\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n updateLayout();\n\n let frame: number | undefined;\n const scheduleUpdate = () => {\n if (frame) return;\n\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n updateLayout();\n });\n };\n\n window.addEventListener('resize', scheduleUpdate);\n window.addEventListener('scroll', scheduleUpdate, true);\n\n return () => {\n window.removeEventListener('resize', scheduleUpdate);\n window.removeEventListener('scroll', scheduleUpdate, true);\n if (frame) window.cancelAnimationFrame(frame);\n };\n }, [isOpen, updateLayout]);\n\n // While the tooltip is there, the content is described by it (read by a screen reader when the\n // content has the focus). `useMemo` keeps the element the same between the renders the tooltip\n // makes by itself, so the content is not rendered again for each of them.\n const trigger = useMemo(() => {\n if (!required || !isOpen || !isValidElement<{ 'aria-describedby'?: string }>(children)) {\n return children;\n }\n\n const describedBy = children.props['aria-describedby'];\n\n return cloneElement(children, {\n 'aria-describedby': describedBy ? `${describedBy} ${id}` : id,\n });\n }, [children, id, isOpen, required]);\n\n const isShown = required && isOpen && layout !== undefined;\n\n return (\n <div\n ref={containerRef}\n className={required ? `relative inline-flex ${containerClassName}` : 'contents'}\n onBlur={closeTooltip}\n onFocus={openTooltip}\n onMouseEnter={openTooltip}\n onMouseLeave={closeTooltip}\n >\n {/* Main Content */}\n {trigger}\n {/* Tooltip */}\n {isShown &&\n createPortal(\n <div\n ref={tooltipRef}\n id={id}\n role=\"tooltip\"\n className={`border-silver-jet-2 bg-platinum-jet fixed z-9999 flex flex-col items-center justify-center rounded-lg border px-3 py-2 text-center whitespace-nowrap backdrop-blur-md transition-all duration-400 ease-in-out after:absolute after:border-8 after:border-solid after:border-transparent after:content-[''] ${isVisible ? 'visible opacity-100' : 'invisible opacity-0'} ${getTooltipArrowCss(layout.placement)} ${className} `}\n style={\n {\n ...layout.position,\n '--tooltip-arrow-shift': `${String(layout.arrowShift)}px`,\n transform: getTooltipTransform(layout.placement, isVisible),\n } as CSSProperties\n }\n >\n <div className=\"text-primary text-xs font-medium\">{title}</div>\n {description && (\n <div className=\"text-tertiary text-[10px] font-light\">{description}</div>\n )}\n </div>,\n document.body,\n )}\n </div>\n );\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beautinique/frontend-components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Shared React UI components for the Beautinique frontends.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"frontend",
|
|
@@ -79,7 +79,6 @@
|
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
81
|
"nanoid": "^6.0.1",
|
|
82
|
-
"tailwind-merge": "^3.7.0",
|
|
83
82
|
"zustand": "^5.0.15"
|
|
84
83
|
},
|
|
85
84
|
"devDependencies": {
|