@astra-kit/ui 0.0.0-stage → 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/LICENSE.md +21 -0
- package/README.md +384 -2
- package/THIRD_PARTY_NOTICES.md +31 -0
- package/assets/fonts/geist-LICENSE.txt +93 -0
- package/assets/fonts/geist-latin-variable.woff2 +0 -0
- package/assets/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
- package/assets/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
- package/assets/fonts/ibmplexmono-LICENSE.txt +93 -0
- package/assets/fonts/inter-LICENSE.txt +93 -0
- package/assets/fonts/inter-latin-variable.woff2 +0 -0
- package/dist/adapters/unpic-image.d.ts +3 -0
- package/dist/adapters/unpic-image.js +98 -0
- package/dist/components/account-menu.d.ts +67 -0
- package/dist/components/account-menu.js +440 -0
- package/dist/components/action-button.d.ts +25 -0
- package/dist/components/action-button.js +264 -0
- package/dist/components/alert.d.ts +31 -0
- package/dist/components/alert.js +503 -0
- package/dist/components/animated-collapse.d.ts +19 -0
- package/dist/components/animated-collapse.js +170 -0
- package/dist/components/animated-count.d.ts +13 -0
- package/dist/components/animated-count.js +105 -0
- package/dist/components/animated-list-item.d.ts +25 -0
- package/dist/components/animated-list-item.js +134 -0
- package/dist/components/animated-theme-toggler.d.ts +12 -0
- package/dist/components/animated-theme-toggler.js +200 -0
- package/dist/components/avatar.d.ts +65 -0
- package/dist/components/avatar.js +463 -0
- package/dist/components/badge.d.ts +21 -0
- package/dist/components/badge.js +297 -0
- package/dist/components/button-interaction.d.ts +23 -0
- package/dist/components/button-interaction.js +22 -0
- package/dist/components/button-label.d.ts +8 -0
- package/dist/components/button-label.js +203 -0
- package/dist/components/button.d.ts +23 -0
- package/dist/components/button.js +145 -0
- package/dist/components/calendar.d.ts +47 -0
- package/dist/components/calendar.js +155 -0
- package/dist/components/card.d.ts +38 -0
- package/dist/components/card.js +904 -0
- package/dist/components/carousel.d.ts +71 -0
- package/dist/components/carousel.js +585 -0
- package/dist/components/checkbox.d.ts +15 -0
- package/dist/components/checkbox.js +324 -0
- package/dist/components/control-button.d.ts +16 -0
- package/dist/components/control-button.js +215 -0
- package/dist/components/data-table.d.ts +118 -0
- package/dist/components/data-table.js +895 -0
- package/dist/components/dialog-surface.d.ts +49 -0
- package/dist/components/dialog-surface.js +220 -0
- package/dist/components/dialog.d.ts +92 -0
- package/dist/components/dialog.js +320 -0
- package/dist/components/dropdown-menu.d.ts +57 -0
- package/dist/components/dropdown-menu.js +107 -0
- package/dist/components/field.d.ts +53 -0
- package/dist/components/field.js +710 -0
- package/dist/components/file-upload.d.ts +88 -0
- package/dist/components/file-upload.js +776 -0
- package/dist/components/filter-presets-bar.d.ts +73 -0
- package/dist/components/filter-presets-bar.js +510 -0
- package/dist/components/filter-query-bar.d.ts +21 -0
- package/dist/components/filter-query-bar.js +881 -0
- package/dist/components/filter-query-grammar.d.ts +188 -0
- package/dist/components/filter-query-grammar.js +875 -0
- package/dist/components/form.d.ts +29 -0
- package/dist/components/form.js +330 -0
- package/dist/components/highlighter.d.ts +15 -0
- package/dist/components/highlighter.js +152 -0
- package/dist/components/hover-card.d.ts +50 -0
- package/dist/components/hover-card.js +80 -0
- package/dist/components/input-group.d.ts +16 -0
- package/dist/components/input-group.js +277 -0
- package/dist/components/input.d.ts +17 -0
- package/dist/components/input.js +120 -0
- package/dist/components/label.d.ts +4 -0
- package/dist/components/label.js +43 -0
- package/dist/components/link.d.ts +9 -0
- package/dist/components/link.js +43 -0
- package/dist/components/morph-text.d.ts +14 -0
- package/dist/components/morph-text.js +210 -0
- package/dist/components/pagination.d.ts +59 -0
- package/dist/components/pagination.js +190 -0
- package/dist/components/popover.d.ts +17 -0
- package/dist/components/popover.js +40 -0
- package/dist/components/presence-swap.d.ts +22 -0
- package/dist/components/presence-swap.js +209 -0
- package/dist/components/primitives/alert-dialog.d.ts +68 -0
- package/dist/components/primitives/alert-dialog.js +629 -0
- package/dist/components/primitives/avatar.d.ts +46 -0
- package/dist/components/primitives/avatar.js +265 -0
- package/dist/components/primitives/calendar.d.ts +37 -0
- package/dist/components/primitives/calendar.js +1250 -0
- package/dist/components/primitives/carousel.d.ts +106 -0
- package/dist/components/primitives/carousel.js +928 -0
- package/dist/components/primitives/dialog.d.ts +62 -0
- package/dist/components/primitives/dialog.js +490 -0
- package/dist/components/primitives/dropdown-menu-items.d.ts +59 -0
- package/dist/components/primitives/dropdown-menu-items.js +265 -0
- package/dist/components/primitives/dropdown-menu.d.ts +64 -0
- package/dist/components/primitives/dropdown-menu.js +560 -0
- package/dist/components/primitives/hover-card.d.ts +50 -0
- package/dist/components/primitives/hover-card.js +507 -0
- package/dist/components/primitives/pagination.d.ts +65 -0
- package/dist/components/primitives/pagination.js +373 -0
- package/dist/components/primitives/popover.d.ts +22 -0
- package/dist/components/primitives/popover.js +213 -0
- package/dist/components/primitives/select.d.ts +37 -0
- package/dist/components/primitives/select.js +428 -0
- package/dist/components/primitives/tooltip.d.ts +30 -0
- package/dist/components/primitives/tooltip.js +277 -0
- package/dist/components/progress-ring.d.ts +20 -0
- package/dist/components/progress-ring.js +53 -0
- package/dist/components/radio-group.d.ts +34 -0
- package/dist/components/radio-group.js +392 -0
- package/dist/components/reaction-button.d.ts +30 -0
- package/dist/components/reaction-button.js +189 -0
- package/dist/components/rich-link-editor.d.ts +25 -0
- package/dist/components/rich-link-editor.js +320 -0
- package/dist/components/rich-markdown-content.d.ts +10 -0
- package/dist/components/rich-markdown-content.js +56 -0
- package/dist/components/rich-text-content.d.ts +19 -0
- package/dist/components/rich-text-content.js +26 -0
- package/dist/components/select.d.ts +55 -0
- package/dist/components/select.js +188 -0
- package/dist/components/separator.d.ts +3 -0
- package/dist/components/separator.js +48 -0
- package/dist/components/sheet.d.ts +19 -0
- package/dist/components/sheet.js +420 -0
- package/dist/components/sidebar-panel-context.d.ts +17 -0
- package/dist/components/sidebar-panel-context.js +14 -0
- package/dist/components/sidebar.d.ts +195 -0
- package/dist/components/sidebar.js +2041 -0
- package/dist/components/skeleton.d.ts +23 -0
- package/dist/components/skeleton.js +334 -0
- package/dist/components/split-button.d.ts +36 -0
- package/dist/components/split-button.js +306 -0
- package/dist/components/svgs/whatsappIcon.d.ts +3 -0
- package/dist/components/svgs/whatsappIcon.js +14 -0
- package/dist/components/switch.d.ts +13 -0
- package/dist/components/switch.js +444 -0
- package/dist/components/table.d.ts +10 -0
- package/dist/components/table.js +298 -0
- package/dist/components/tabs.d.ts +36 -0
- package/dist/components/tabs.js +636 -0
- package/dist/components/textarea.d.ts +16 -0
- package/dist/components/textarea.js +111 -0
- package/dist/components/themed-toaster.d.ts +7 -0
- package/dist/components/themed-toaster.js +86 -0
- package/dist/components/toaster.d.ts +12 -0
- package/dist/components/toaster.js +62 -0
- package/dist/components/tooltip.d.ts +43 -0
- package/dist/components/tooltip.js +65 -0
- package/dist/components/typing-animation.d.ts +34 -0
- package/dist/components/typing-animation.js +389 -0
- package/dist/constants/action-button.d.ts +20 -0
- package/dist/constants/action-button.js +17 -0
- package/dist/constants/alert.d.ts +16 -0
- package/dist/constants/alert.js +13 -0
- package/dist/constants/avatar.d.ts +38 -0
- package/dist/constants/avatar.js +32 -0
- package/dist/constants/badge.d.ts +6 -0
- package/dist/constants/badge.js +6 -0
- package/dist/constants/button.d.ts +16 -0
- package/dist/constants/button.js +16 -0
- package/dist/constants/calendar.d.ts +36 -0
- package/dist/constants/calendar.js +34 -0
- package/dist/constants/card.d.ts +23 -0
- package/dist/constants/card.js +20 -0
- package/dist/constants/carousel.d.ts +55 -0
- package/dist/constants/carousel.js +74 -0
- package/dist/constants/checkbox.d.ts +17 -0
- package/dist/constants/checkbox.js +17 -0
- package/dist/constants/dialog.d.ts +11 -0
- package/dist/constants/dialog.js +10 -0
- package/dist/constants/dropdown-menu.d.ts +10 -0
- package/dist/constants/dropdown-menu.js +37 -0
- package/dist/constants/field.d.ts +24 -0
- package/dist/constants/field.js +24 -0
- package/dist/constants/hover-card.d.ts +37 -0
- package/dist/constants/hover-card.js +85 -0
- package/dist/constants/morph-text.d.ts +13 -0
- package/dist/constants/morph-text.js +13 -0
- package/dist/constants/motion.d.ts +12 -0
- package/dist/constants/motion.js +12 -0
- package/dist/constants/pagination.d.ts +20 -0
- package/dist/constants/pagination.js +20 -0
- package/dist/constants/popover.d.ts +7 -0
- package/dist/constants/popover.js +33 -0
- package/dist/constants/radio-group.d.ts +10 -0
- package/dist/constants/radio-group.js +10 -0
- package/dist/constants/select.d.ts +7 -0
- package/dist/constants/select.js +34 -0
- package/dist/constants/sidebar.d.ts +9 -0
- package/dist/constants/sidebar.js +17 -0
- package/dist/constants/skeleton.d.ts +17 -0
- package/dist/constants/skeleton.js +17 -0
- package/dist/constants/split-button.d.ts +7 -0
- package/dist/constants/split-button.js +5 -0
- package/dist/constants/switch.d.ts +33 -0
- package/dist/constants/switch.js +41 -0
- package/dist/constants/tabs.d.ts +17 -0
- package/dist/constants/tabs.js +17 -0
- package/dist/constants/toast.d.ts +3 -0
- package/dist/constants/toast.js +3 -0
- package/dist/constants/tooltip.d.ts +13 -0
- package/dist/constants/tooltip.js +52 -0
- package/dist/hooks/use-horizontal-swipe.d.ts +23 -0
- package/dist/hooks/use-horizontal-swipe.js +80 -0
- package/dist/hooks/use-is-hydrated.d.ts +6 -0
- package/dist/hooks/use-is-hydrated.js +20 -0
- package/dist/hooks/use-mobile.d.ts +1 -0
- package/dist/hooks/use-mobile.js +19 -0
- package/dist/hooks/use-prefers-reduced-motion.d.ts +2 -0
- package/dist/hooks/use-prefers-reduced-motion.js +27 -0
- package/dist/hooks/use-rich-link-editor.d.ts +55 -0
- package/dist/hooks/use-rich-link-editor.js +515 -0
- package/dist/hooks/use-sidebar-persistence.d.ts +6 -0
- package/dist/hooks/use-sidebar-persistence.js +52 -0
- package/dist/hooks/use-today.d.ts +7 -0
- package/dist/hooks/use-today.js +50 -0
- package/dist/hooks/use-viewer-time-zone.d.ts +6 -0
- package/dist/hooks/use-viewer-time-zone.js +20 -0
- package/dist/hooks.d.ts +11 -0
- package/dist/hooks.js +11 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.js +69 -0
- package/dist/lib/browser-clipboard.d.ts +13 -0
- package/dist/lib/browser-clipboard.js +48 -0
- package/dist/lib/column-filter-value.d.ts +12 -0
- package/dist/lib/column-filter-value.js +52 -0
- package/dist/lib/file-acceptance.d.ts +43 -0
- package/dist/lib/file-acceptance.js +107 -0
- package/dist/lib/format-file-size.d.ts +16 -0
- package/dist/lib/format-file-size.js +34 -0
- package/dist/lib/fuzzy-search.d.ts +17 -0
- package/dist/lib/fuzzy-search.js +183 -0
- package/dist/lib/horizontal-swipe.d.ts +23 -0
- package/dist/lib/horizontal-swipe.js +29 -0
- package/dist/lib/image-dimensions.d.ts +2 -0
- package/dist/lib/image-dimensions.js +7 -0
- package/dist/lib/name-initials.d.ts +7 -0
- package/dist/lib/name-initials.js +11 -0
- package/dist/lib/rich-text/link-markdown-constants.d.ts +147 -0
- package/dist/lib/rich-text/link-markdown-constants.js +458 -0
- package/dist/lib/rich-text/link-markdown-types.d.ts +53 -0
- package/dist/lib/rich-text/link-markdown-types.js +1 -0
- package/dist/lib/rich-text/link-markdown.d.ts +193 -0
- package/dist/lib/rich-text/link-markdown.js +592 -0
- package/dist/lib/rich-text/rich-markdown.d.ts +41 -0
- package/dist/lib/rich-text/rich-markdown.js +105 -0
- package/dist/lib/rich-text/rich-text-editor-dom.d.ts +26 -0
- package/dist/lib/rich-text/rich-text-editor-dom.js +79 -0
- package/dist/lib/toast-layer.d.ts +24 -0
- package/dist/lib/toast-layer.js +76 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +2 -0
- package/dist/lib/year-month-filter.d.ts +16 -0
- package/dist/lib/year-month-filter.js +46 -0
- package/dist/motion/arc-floating-slot.d.ts +40 -0
- package/dist/motion/arc-floating-slot.js +177 -0
- package/dist/motion/arc-press.d.ts +6 -0
- package/dist/motion/arc-press.js +59 -0
- package/dist/motion/arc-swap.d.ts +22 -0
- package/dist/motion/arc-swap.js +49 -0
- package/dist/motion/arc-tokens.d.ts +53 -0
- package/dist/motion/arc-tokens.js +73 -0
- package/dist/motion/glide-indicator.d.ts +69 -0
- package/dist/motion/glide-indicator.js +309 -0
- package/dist/motion/glide-slot.d.ts +9 -0
- package/dist/motion/glide-slot.js +71 -0
- package/dist/motion/motion-slot.d.ts +12 -0
- package/dist/motion/motion-slot.js +376 -0
- package/dist/motion/overlay-warmth.d.ts +24 -0
- package/dist/motion/overlay-warmth.js +70 -0
- package/dist/motion/presence.d.ts +40 -0
- package/dist/motion/presence.js +101 -0
- package/dist/motion/surface-keyframes.d.ts +24 -0
- package/dist/motion/surface-keyframes.js +141 -0
- package/dist/motion/tokens.d.ts +81 -0
- package/dist/motion/tokens.js +67 -0
- package/dist/motion/use-attached-element.d.ts +7 -0
- package/dist/motion/use-attached-element.js +22 -0
- package/dist/motion/use-morph-width.d.ts +13 -0
- package/dist/motion/use-morph-width.js +59 -0
- package/dist/next.d.ts +14 -0
- package/dist/next.js +79 -0
- package/dist/providers/astra-ui-provider.d.ts +27 -0
- package/dist/providers/astra-ui-provider.js +100 -0
- package/dist/providers/native-provider.d.ts +4 -0
- package/dist/providers/native-provider.js +45 -0
- package/dist/sonner.d.ts +7 -0
- package/dist/sonner.js +8 -0
- package/dist/styles.css +2 -0
- package/dist/tanstack.d.ts +11 -0
- package/dist/tanstack.js +50 -0
- package/dist/theme.d.ts +3 -0
- package/dist/theme.js +1 -0
- package/dist/types/data-table.d.ts +27 -0
- package/dist/types/data-table.js +1 -0
- package/fonts.css +5 -0
- package/package.json +450 -4
- package/styles.css +4 -0
- package/theme.css +248 -0
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { c as _c } from "react/compiler-runtime";
|
|
3
|
+
/** Owns the state of `RichLinkEditor`: content, tracked links, popover and selection. */
|
|
4
|
+
import { useLayoutEffect, useRef, useState } from "react";
|
|
5
|
+
import { RICH_LINK_KIND, RICH_LINK_POPOVER_MODE, RICH_PREVIEW_LINK_SOURCE, RICH_TEXT_CLIPBOARD_DATA_TYPE, RICH_TEXT_EDITOR_INPUT_TYPE, RICH_TEXT_EDITOR_KEY, RICH_TEXT_EDITOR_KEY_LENGTH, RICH_TEXT_EDITOR_TEXT, RICH_TEXT_EDITOR_WORD_DIRECTION } from "../lib/rich-text/link-markdown-constants.js";
|
|
6
|
+
import { deserializeMarkdownForEditor, getLinksAfterTextChange, getWordDeletionRange, isLinkSynchronized, normalizeMarkdownUrl, parsePreviewSegments, rangesOverlap, serializeEditorContent } from "../lib/rich-text/link-markdown.js";
|
|
7
|
+
import { getEditorSelectionRange, setEditorSelectionRange } from "../lib/rich-text/rich-text-editor-dom.js";
|
|
8
|
+
const EMPTY_TEXT = "";
|
|
9
|
+
/**
|
|
10
|
+
* Controls a rich link editor backed by a `contentEditable` element: it owns the
|
|
11
|
+
* plain-text content, the tracked explicit/suppressed links, the link popover
|
|
12
|
+
* state, and the selection bookkeeping, and exposes serialize/reset/snapshot
|
|
13
|
+
* helpers so a feature can persist or restore the value. The DOM rendering lives
|
|
14
|
+
* in `RichLinkEditor`.
|
|
15
|
+
*/
|
|
16
|
+
export function useRichLinkEditor(t0) {
|
|
17
|
+
const $ = _c(72);
|
|
18
|
+
let t1;
|
|
19
|
+
if ($[0] !== t0) {
|
|
20
|
+
t1 = t0 === undefined ? {} : t0;
|
|
21
|
+
$[0] = t0;
|
|
22
|
+
$[1] = t1;
|
|
23
|
+
} else {
|
|
24
|
+
t1 = $[1];
|
|
25
|
+
}
|
|
26
|
+
const options = t1;
|
|
27
|
+
const editorRef = useRef(null);
|
|
28
|
+
let t2;
|
|
29
|
+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
|
30
|
+
t2 = (node) => {
|
|
31
|
+
editorRef.current = node;
|
|
32
|
+
};
|
|
33
|
+
$[2] = t2;
|
|
34
|
+
} else {
|
|
35
|
+
t2 = $[2];
|
|
36
|
+
}
|
|
37
|
+
const setEditorElement = t2;
|
|
38
|
+
const pendingSelectionRef = useRef(null);
|
|
39
|
+
let t3;
|
|
40
|
+
if ($[3] !== options.initialMarkdown) {
|
|
41
|
+
t3 = () => deserializeMarkdownForEditor(options.initialMarkdown ?? EMPTY_TEXT).content;
|
|
42
|
+
$[3] = options.initialMarkdown;
|
|
43
|
+
$[4] = t3;
|
|
44
|
+
} else {
|
|
45
|
+
t3 = $[4];
|
|
46
|
+
}
|
|
47
|
+
const [content, setContent] = useState(t3);
|
|
48
|
+
let t4;
|
|
49
|
+
if ($[5] !== options.initialMarkdown) {
|
|
50
|
+
t4 = () => deserializeMarkdownForEditor(options.initialMarkdown ?? EMPTY_TEXT).links;
|
|
51
|
+
$[5] = options.initialMarkdown;
|
|
52
|
+
$[6] = t4;
|
|
53
|
+
} else {
|
|
54
|
+
t4 = $[6];
|
|
55
|
+
}
|
|
56
|
+
const [links, setLinks] = useState(t4);
|
|
57
|
+
const [activeLink, setActiveLink] = useState(null);
|
|
58
|
+
const [linkTextInput, setLinkTextInput] = useState("");
|
|
59
|
+
const [linkUrlInput, setLinkUrlInput] = useState("");
|
|
60
|
+
const [popoverMode, setPopoverMode] = useState(RICH_LINK_POPOVER_MODE.actions);
|
|
61
|
+
let t5;
|
|
62
|
+
if ($[7] !== content || $[8] !== links) {
|
|
63
|
+
t5 = parsePreviewSegments(content, links);
|
|
64
|
+
$[7] = content;
|
|
65
|
+
$[8] = links;
|
|
66
|
+
$[9] = t5;
|
|
67
|
+
} else {
|
|
68
|
+
t5 = $[9];
|
|
69
|
+
}
|
|
70
|
+
const segments = t5;
|
|
71
|
+
const hasContent = content.length > 0;
|
|
72
|
+
let t6;
|
|
73
|
+
if ($[10] !== linkUrlInput) {
|
|
74
|
+
t6 = normalizeMarkdownUrl(linkUrlInput);
|
|
75
|
+
$[10] = linkUrlInput;
|
|
76
|
+
$[11] = t6;
|
|
77
|
+
} else {
|
|
78
|
+
t6 = $[11];
|
|
79
|
+
}
|
|
80
|
+
const normalizedLinkUrlInput = t6;
|
|
81
|
+
let t7;
|
|
82
|
+
if ($[12] !== linkUrlInput || $[13] !== normalizedLinkUrlInput) {
|
|
83
|
+
t7 = linkUrlInput.trim().length > 0 && normalizedLinkUrlInput === null;
|
|
84
|
+
$[12] = linkUrlInput;
|
|
85
|
+
$[13] = normalizedLinkUrlInput;
|
|
86
|
+
$[14] = t7;
|
|
87
|
+
} else {
|
|
88
|
+
t7 = $[14];
|
|
89
|
+
}
|
|
90
|
+
const hasInvalidLinkUrl = t7;
|
|
91
|
+
let t8;
|
|
92
|
+
if ($[15] !== linkTextInput || $[16] !== normalizedLinkUrlInput) {
|
|
93
|
+
t8 = normalizedLinkUrlInput !== null && linkTextInput.trim().length > 0;
|
|
94
|
+
$[15] = linkTextInput;
|
|
95
|
+
$[16] = normalizedLinkUrlInput;
|
|
96
|
+
$[17] = t8;
|
|
97
|
+
} else {
|
|
98
|
+
t8 = $[17];
|
|
99
|
+
}
|
|
100
|
+
const isLinkEditValid = t8;
|
|
101
|
+
let t9;
|
|
102
|
+
if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
|
|
103
|
+
t9 = () => {
|
|
104
|
+
const editor = editorRef.current;
|
|
105
|
+
const selectionRange = pendingSelectionRef.current;
|
|
106
|
+
if (!editor || !selectionRange || !editor.contains(document.activeElement)) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
setEditorSelectionRange(editor, selectionRange);
|
|
110
|
+
pendingSelectionRef.current = null;
|
|
111
|
+
};
|
|
112
|
+
$[18] = t9;
|
|
113
|
+
} else {
|
|
114
|
+
t9 = $[18];
|
|
115
|
+
}
|
|
116
|
+
let t10;
|
|
117
|
+
if ($[19] !== content || $[20] !== links) {
|
|
118
|
+
t10 = [content, links];
|
|
119
|
+
$[19] = content;
|
|
120
|
+
$[20] = links;
|
|
121
|
+
$[21] = t10;
|
|
122
|
+
} else {
|
|
123
|
+
t10 = $[21];
|
|
124
|
+
}
|
|
125
|
+
useLayoutEffect(t9, t10);
|
|
126
|
+
let t11;
|
|
127
|
+
if ($[22] !== content || $[23] !== options) {
|
|
128
|
+
t11 = (nextContent) => {
|
|
129
|
+
setLinks((currentLinks) => getLinksAfterTextChange({
|
|
130
|
+
links: currentLinks,
|
|
131
|
+
nextText: nextContent,
|
|
132
|
+
previousText: content
|
|
133
|
+
}));
|
|
134
|
+
setContent(nextContent);
|
|
135
|
+
options.onContentChange?.();
|
|
136
|
+
};
|
|
137
|
+
$[22] = content;
|
|
138
|
+
$[23] = options;
|
|
139
|
+
$[24] = t11;
|
|
140
|
+
} else {
|
|
141
|
+
t11 = $[24];
|
|
142
|
+
}
|
|
143
|
+
const handleContentChange = t11;
|
|
144
|
+
let t12;
|
|
145
|
+
if ($[25] !== content || $[26] !== handleContentChange) {
|
|
146
|
+
t12 = (replacementText, selectionRange_0) => {
|
|
147
|
+
const nextSelectionOffset = selectionRange_0.start + replacementText.length;
|
|
148
|
+
const nextContent_0 = content.slice(0, selectionRange_0.start) + replacementText + content.slice(selectionRange_0.end);
|
|
149
|
+
pendingSelectionRef.current = {
|
|
150
|
+
end: nextSelectionOffset,
|
|
151
|
+
start: nextSelectionOffset
|
|
152
|
+
};
|
|
153
|
+
handleContentChange(nextContent_0);
|
|
154
|
+
};
|
|
155
|
+
$[25] = content;
|
|
156
|
+
$[26] = handleContentChange;
|
|
157
|
+
$[27] = t12;
|
|
158
|
+
} else {
|
|
159
|
+
t12 = $[27];
|
|
160
|
+
}
|
|
161
|
+
const replaceContentText = t12;
|
|
162
|
+
let t13;
|
|
163
|
+
if ($[28] !== content || $[29] !== options || $[30] !== replaceContentText) {
|
|
164
|
+
t13 = (event) => {
|
|
165
|
+
const pastedText = event.clipboardData.getData(RICH_TEXT_CLIPBOARD_DATA_TYPE.plainText);
|
|
166
|
+
const pastedUrl = normalizeMarkdownUrl(pastedText);
|
|
167
|
+
const selectionRange_1 = getEditorSelectionRange(event.currentTarget) ?? {
|
|
168
|
+
end: content.length,
|
|
169
|
+
start: content.length
|
|
170
|
+
};
|
|
171
|
+
const hasSelectedText = selectionRange_1.start !== selectionRange_1.end;
|
|
172
|
+
event.preventDefault();
|
|
173
|
+
if (!pastedUrl || !hasSelectedText) {
|
|
174
|
+
replaceContentText(pastedText, selectionRange_1);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
pendingSelectionRef.current = selectionRange_1;
|
|
178
|
+
setLinks((currentLinks_0) => [...currentLinks_0.filter((link) => !rangesOverlap(link, {
|
|
179
|
+
end: selectionRange_1.end,
|
|
180
|
+
start: selectionRange_1.start
|
|
181
|
+
})), {
|
|
182
|
+
end: selectionRange_1.end,
|
|
183
|
+
id: crypto.randomUUID(),
|
|
184
|
+
isSynced: isLinkSynchronized(content.slice(selectionRange_1.start, selectionRange_1.end), pastedUrl),
|
|
185
|
+
kind: RICH_LINK_KIND.explicit,
|
|
186
|
+
start: selectionRange_1.start,
|
|
187
|
+
url: pastedUrl
|
|
188
|
+
}]);
|
|
189
|
+
options.onContentChange?.();
|
|
190
|
+
};
|
|
191
|
+
$[28] = content;
|
|
192
|
+
$[29] = options;
|
|
193
|
+
$[30] = replaceContentText;
|
|
194
|
+
$[31] = t13;
|
|
195
|
+
} else {
|
|
196
|
+
t13 = $[31];
|
|
197
|
+
}
|
|
198
|
+
const handlePaste = t13;
|
|
199
|
+
let t14;
|
|
200
|
+
if ($[32] !== content || $[33] !== replaceContentText) {
|
|
201
|
+
t14 = (event_0) => {
|
|
202
|
+
if (event_0.altKey || event_0.metaKey) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (event_0.ctrlKey && event_0.key !== RICH_TEXT_EDITOR_KEY.backspace && event_0.key !== RICH_TEXT_EDITOR_KEY.delete) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const selectionRange_2 = getEditorSelectionRange(event_0.currentTarget) ?? {
|
|
209
|
+
end: content.length,
|
|
210
|
+
start: content.length
|
|
211
|
+
};
|
|
212
|
+
let replacementText_0 = null;
|
|
213
|
+
let replacementRange = selectionRange_2;
|
|
214
|
+
if (event_0.key.length === RICH_TEXT_EDITOR_KEY_LENGTH.character) {
|
|
215
|
+
replacementText_0 = event_0.key;
|
|
216
|
+
}
|
|
217
|
+
if (event_0.key === RICH_TEXT_EDITOR_KEY.enter) {
|
|
218
|
+
replacementText_0 = RICH_TEXT_EDITOR_TEXT.lineBreak;
|
|
219
|
+
}
|
|
220
|
+
if (event_0.key === RICH_TEXT_EDITOR_KEY.backspace) {
|
|
221
|
+
replacementText_0 = EMPTY_TEXT;
|
|
222
|
+
replacementRange = event_0.ctrlKey ? getWordDeletionRange({
|
|
223
|
+
direction: RICH_TEXT_EDITOR_WORD_DIRECTION.backward,
|
|
224
|
+
selectionRange: selectionRange_2,
|
|
225
|
+
text: content
|
|
226
|
+
}) : selectionRange_2.start === selectionRange_2.end ? {
|
|
227
|
+
end: selectionRange_2.end,
|
|
228
|
+
start: Math.max(selectionRange_2.start - 1, 0)
|
|
229
|
+
} : selectionRange_2;
|
|
230
|
+
}
|
|
231
|
+
if (event_0.key === RICH_TEXT_EDITOR_KEY.delete) {
|
|
232
|
+
replacementText_0 = EMPTY_TEXT;
|
|
233
|
+
replacementRange = event_0.ctrlKey ? getWordDeletionRange({
|
|
234
|
+
direction: RICH_TEXT_EDITOR_WORD_DIRECTION.forward,
|
|
235
|
+
selectionRange: selectionRange_2,
|
|
236
|
+
text: content
|
|
237
|
+
}) : selectionRange_2.start === selectionRange_2.end ? {
|
|
238
|
+
end: Math.min(selectionRange_2.end + 1, content.length),
|
|
239
|
+
start: selectionRange_2.start
|
|
240
|
+
} : selectionRange_2;
|
|
241
|
+
}
|
|
242
|
+
if (replacementText_0 === null) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
event_0.preventDefault();
|
|
246
|
+
replaceContentText(replacementText_0, replacementRange);
|
|
247
|
+
};
|
|
248
|
+
$[32] = content;
|
|
249
|
+
$[33] = replaceContentText;
|
|
250
|
+
$[34] = t14;
|
|
251
|
+
} else {
|
|
252
|
+
t14 = $[34];
|
|
253
|
+
}
|
|
254
|
+
const handleKeyDown = t14;
|
|
255
|
+
let t15;
|
|
256
|
+
if ($[35] !== content.length || $[36] !== replaceContentText) {
|
|
257
|
+
t15 = (event_1) => {
|
|
258
|
+
const nativeEvent = event_1.nativeEvent;
|
|
259
|
+
const selectionRange_3 = getEditorSelectionRange(event_1.currentTarget) ?? {
|
|
260
|
+
end: content.length,
|
|
261
|
+
start: content.length
|
|
262
|
+
};
|
|
263
|
+
let replacementText_1 = null;
|
|
264
|
+
let replacementRange_0 = selectionRange_3;
|
|
265
|
+
if (nativeEvent.inputType === RICH_TEXT_EDITOR_INPUT_TYPE.insertText) {
|
|
266
|
+
replacementText_1 = nativeEvent.data ?? EMPTY_TEXT;
|
|
267
|
+
}
|
|
268
|
+
if (nativeEvent.inputType === RICH_TEXT_EDITOR_INPUT_TYPE.insertParagraph || nativeEvent.inputType === RICH_TEXT_EDITOR_INPUT_TYPE.insertLineBreak) {
|
|
269
|
+
replacementText_1 = RICH_TEXT_EDITOR_TEXT.lineBreak;
|
|
270
|
+
}
|
|
271
|
+
if (nativeEvent.inputType === RICH_TEXT_EDITOR_INPUT_TYPE.deleteContentBackward) {
|
|
272
|
+
replacementText_1 = EMPTY_TEXT;
|
|
273
|
+
replacementRange_0 = selectionRange_3.start === selectionRange_3.end ? {
|
|
274
|
+
end: selectionRange_3.end,
|
|
275
|
+
start: Math.max(selectionRange_3.start - 1, 0)
|
|
276
|
+
} : selectionRange_3;
|
|
277
|
+
}
|
|
278
|
+
if (nativeEvent.inputType === RICH_TEXT_EDITOR_INPUT_TYPE.deleteContentForward) {
|
|
279
|
+
replacementText_1 = EMPTY_TEXT;
|
|
280
|
+
replacementRange_0 = selectionRange_3.start === selectionRange_3.end ? {
|
|
281
|
+
end: Math.min(selectionRange_3.end + 1, content.length),
|
|
282
|
+
start: selectionRange_3.start
|
|
283
|
+
} : selectionRange_3;
|
|
284
|
+
}
|
|
285
|
+
if (replacementText_1 === null) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
event_1.preventDefault();
|
|
289
|
+
replaceContentText(replacementText_1, replacementRange_0);
|
|
290
|
+
};
|
|
291
|
+
$[35] = content.length;
|
|
292
|
+
$[36] = replaceContentText;
|
|
293
|
+
$[37] = t15;
|
|
294
|
+
} else {
|
|
295
|
+
t15 = $[37];
|
|
296
|
+
}
|
|
297
|
+
const handleBeforeInput = t15;
|
|
298
|
+
let t16;
|
|
299
|
+
if ($[38] !== handleContentChange) {
|
|
300
|
+
t16 = (event_2) => {
|
|
301
|
+
const selectionRange_4 = getEditorSelectionRange(event_2.currentTarget);
|
|
302
|
+
if (selectionRange_4) {
|
|
303
|
+
pendingSelectionRef.current = selectionRange_4;
|
|
304
|
+
}
|
|
305
|
+
handleContentChange(event_2.currentTarget.textContent ?? EMPTY_TEXT);
|
|
306
|
+
};
|
|
307
|
+
$[38] = handleContentChange;
|
|
308
|
+
$[39] = t16;
|
|
309
|
+
} else {
|
|
310
|
+
t16 = $[39];
|
|
311
|
+
}
|
|
312
|
+
const handleInput = t16;
|
|
313
|
+
let t17;
|
|
314
|
+
if ($[40] === Symbol.for("react.memo_cache_sentinel")) {
|
|
315
|
+
t17 = (segment) => {
|
|
316
|
+
setActiveLink(segment);
|
|
317
|
+
setLinkTextInput(segment.text);
|
|
318
|
+
setLinkUrlInput(segment.url);
|
|
319
|
+
setPopoverMode(RICH_LINK_POPOVER_MODE.actions);
|
|
320
|
+
};
|
|
321
|
+
$[40] = t17;
|
|
322
|
+
} else {
|
|
323
|
+
t17 = $[40];
|
|
324
|
+
}
|
|
325
|
+
const openLinkPopover = t17;
|
|
326
|
+
let t18;
|
|
327
|
+
if ($[41] === Symbol.for("react.memo_cache_sentinel")) {
|
|
328
|
+
t18 = () => {
|
|
329
|
+
setActiveLink(null);
|
|
330
|
+
setLinkTextInput(EMPTY_TEXT);
|
|
331
|
+
setLinkUrlInput(EMPTY_TEXT);
|
|
332
|
+
setPopoverMode(RICH_LINK_POPOVER_MODE.actions);
|
|
333
|
+
};
|
|
334
|
+
$[41] = t18;
|
|
335
|
+
} else {
|
|
336
|
+
t18 = $[41];
|
|
337
|
+
}
|
|
338
|
+
const closeLinkPopover = t18;
|
|
339
|
+
let t19;
|
|
340
|
+
if ($[42] === Symbol.for("react.memo_cache_sentinel")) {
|
|
341
|
+
t19 = (segment_0) => {
|
|
342
|
+
const shouldSuppressVisibleUrl = Boolean(normalizeMarkdownUrl(segment_0.text));
|
|
343
|
+
const suppressedLink = {
|
|
344
|
+
end: segment_0.end,
|
|
345
|
+
id: crypto.randomUUID(),
|
|
346
|
+
kind: RICH_LINK_KIND.suppressed,
|
|
347
|
+
start: segment_0.start
|
|
348
|
+
};
|
|
349
|
+
setLinks((currentLinks_1) => {
|
|
350
|
+
const linksWithoutRemovedExplicitLink = segment_0.source === RICH_PREVIEW_LINK_SOURCE.explicit && segment_0.id ? currentLinks_1.filter((link_0) => link_0.id !== segment_0.id) : currentLinks_1;
|
|
351
|
+
return shouldSuppressVisibleUrl || segment_0.source === RICH_PREVIEW_LINK_SOURCE.automatic ? [...linksWithoutRemovedExplicitLink, suppressedLink] : linksWithoutRemovedExplicitLink;
|
|
352
|
+
});
|
|
353
|
+
closeLinkPopover();
|
|
354
|
+
};
|
|
355
|
+
$[42] = t19;
|
|
356
|
+
} else {
|
|
357
|
+
t19 = $[42];
|
|
358
|
+
}
|
|
359
|
+
const removeLink = t19;
|
|
360
|
+
let t20;
|
|
361
|
+
if ($[43] !== content || $[44] !== linkTextInput || $[45] !== linkUrlInput) {
|
|
362
|
+
t20 = (segment_1) => {
|
|
363
|
+
const nextUrl = normalizeMarkdownUrl(linkUrlInput);
|
|
364
|
+
const nextText = linkTextInput;
|
|
365
|
+
if (!nextUrl || !nextText.trim()) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const nextContent_1 = content.slice(0, segment_1.start) + nextText + content.slice(segment_1.end);
|
|
369
|
+
const nextEnd = segment_1.start + nextText.length;
|
|
370
|
+
const nextLinkRange = {
|
|
371
|
+
end: nextEnd,
|
|
372
|
+
start: segment_1.start
|
|
373
|
+
};
|
|
374
|
+
pendingSelectionRef.current = {
|
|
375
|
+
end: nextEnd,
|
|
376
|
+
start: nextEnd
|
|
377
|
+
};
|
|
378
|
+
setContent(nextContent_1);
|
|
379
|
+
setLinks((currentLinks_2) => {
|
|
380
|
+
const adjustedLinks = getLinksAfterTextChange({
|
|
381
|
+
links: currentLinks_2,
|
|
382
|
+
nextText: nextContent_1,
|
|
383
|
+
previousText: content
|
|
384
|
+
});
|
|
385
|
+
return [...adjustedLinks.filter((link_1) => {
|
|
386
|
+
if (segment_1.id && link_1.id === segment_1.id) {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
return !rangesOverlap(link_1, nextLinkRange);
|
|
390
|
+
}), {
|
|
391
|
+
end: nextEnd,
|
|
392
|
+
id: segment_1.id ?? crypto.randomUUID(),
|
|
393
|
+
isSynced: isLinkSynchronized(nextText, nextUrl),
|
|
394
|
+
kind: RICH_LINK_KIND.explicit,
|
|
395
|
+
start: segment_1.start,
|
|
396
|
+
url: nextUrl
|
|
397
|
+
}];
|
|
398
|
+
});
|
|
399
|
+
closeLinkPopover();
|
|
400
|
+
};
|
|
401
|
+
$[43] = content;
|
|
402
|
+
$[44] = linkTextInput;
|
|
403
|
+
$[45] = linkUrlInput;
|
|
404
|
+
$[46] = t20;
|
|
405
|
+
} else {
|
|
406
|
+
t20 = $[46];
|
|
407
|
+
}
|
|
408
|
+
const saveLinkEdit = t20;
|
|
409
|
+
let t21;
|
|
410
|
+
if ($[47] !== content || $[48] !== links) {
|
|
411
|
+
t21 = () => serializeEditorContent(content, links);
|
|
412
|
+
$[47] = content;
|
|
413
|
+
$[48] = links;
|
|
414
|
+
$[49] = t21;
|
|
415
|
+
} else {
|
|
416
|
+
t21 = $[49];
|
|
417
|
+
}
|
|
418
|
+
const serialize = t21;
|
|
419
|
+
let t22;
|
|
420
|
+
if ($[50] === Symbol.for("react.memo_cache_sentinel")) {
|
|
421
|
+
t22 = (markdown) => {
|
|
422
|
+
const nextState = deserializeMarkdownForEditor(markdown ?? EMPTY_TEXT);
|
|
423
|
+
pendingSelectionRef.current = null;
|
|
424
|
+
setContent(nextState.content);
|
|
425
|
+
setLinks(nextState.links);
|
|
426
|
+
closeLinkPopover();
|
|
427
|
+
};
|
|
428
|
+
$[50] = t22;
|
|
429
|
+
} else {
|
|
430
|
+
t22 = $[50];
|
|
431
|
+
}
|
|
432
|
+
const reset = t22;
|
|
433
|
+
let t23;
|
|
434
|
+
if ($[51] !== content || $[52] !== links) {
|
|
435
|
+
t23 = () => ({
|
|
436
|
+
content,
|
|
437
|
+
links: links.map(_temp)
|
|
438
|
+
});
|
|
439
|
+
$[51] = content;
|
|
440
|
+
$[52] = links;
|
|
441
|
+
$[53] = t23;
|
|
442
|
+
} else {
|
|
443
|
+
t23 = $[53];
|
|
444
|
+
}
|
|
445
|
+
const getDisplayState = t23;
|
|
446
|
+
let t24;
|
|
447
|
+
if ($[54] === Symbol.for("react.memo_cache_sentinel")) {
|
|
448
|
+
t24 = (state) => {
|
|
449
|
+
pendingSelectionRef.current = null;
|
|
450
|
+
setContent(state.content);
|
|
451
|
+
setLinks(state.links.map(_temp2));
|
|
452
|
+
closeLinkPopover();
|
|
453
|
+
};
|
|
454
|
+
$[54] = t24;
|
|
455
|
+
} else {
|
|
456
|
+
t24 = $[54];
|
|
457
|
+
}
|
|
458
|
+
const loadFromDisplay = t24;
|
|
459
|
+
let t25;
|
|
460
|
+
if ($[55] !== activeLink || $[56] !== content || $[57] !== getDisplayState || $[58] !== handleBeforeInput || $[59] !== handleInput || $[60] !== handleKeyDown || $[61] !== handlePaste || $[62] !== hasContent || $[63] !== hasInvalidLinkUrl || $[64] !== isLinkEditValid || $[65] !== linkTextInput || $[66] !== linkUrlInput || $[67] !== popoverMode || $[68] !== saveLinkEdit || $[69] !== segments || $[70] !== serialize) {
|
|
461
|
+
t25 = {
|
|
462
|
+
activeLink,
|
|
463
|
+
closeLinkPopover,
|
|
464
|
+
content,
|
|
465
|
+
getDisplayState,
|
|
466
|
+
handleBeforeInput,
|
|
467
|
+
handleInput,
|
|
468
|
+
handleKeyDown,
|
|
469
|
+
handlePaste,
|
|
470
|
+
hasContent,
|
|
471
|
+
hasInvalidLinkUrl,
|
|
472
|
+
isLinkEditValid,
|
|
473
|
+
linkTextInput,
|
|
474
|
+
linkUrlInput,
|
|
475
|
+
loadFromDisplay,
|
|
476
|
+
openLinkPopover,
|
|
477
|
+
popoverMode,
|
|
478
|
+
removeLink,
|
|
479
|
+
reset,
|
|
480
|
+
saveLinkEdit,
|
|
481
|
+
segments,
|
|
482
|
+
serialize,
|
|
483
|
+
setEditorElement,
|
|
484
|
+
setLinkTextInput,
|
|
485
|
+
setLinkUrlInput,
|
|
486
|
+
setPopoverMode
|
|
487
|
+
};
|
|
488
|
+
$[55] = activeLink;
|
|
489
|
+
$[56] = content;
|
|
490
|
+
$[57] = getDisplayState;
|
|
491
|
+
$[58] = handleBeforeInput;
|
|
492
|
+
$[59] = handleInput;
|
|
493
|
+
$[60] = handleKeyDown;
|
|
494
|
+
$[61] = handlePaste;
|
|
495
|
+
$[62] = hasContent;
|
|
496
|
+
$[63] = hasInvalidLinkUrl;
|
|
497
|
+
$[64] = isLinkEditValid;
|
|
498
|
+
$[65] = linkTextInput;
|
|
499
|
+
$[66] = linkUrlInput;
|
|
500
|
+
$[67] = popoverMode;
|
|
501
|
+
$[68] = saveLinkEdit;
|
|
502
|
+
$[69] = segments;
|
|
503
|
+
$[70] = serialize;
|
|
504
|
+
$[71] = t25;
|
|
505
|
+
} else {
|
|
506
|
+
t25 = $[71];
|
|
507
|
+
}
|
|
508
|
+
return t25;
|
|
509
|
+
}
|
|
510
|
+
function _temp2(link_3) {
|
|
511
|
+
return { ...link_3 };
|
|
512
|
+
}
|
|
513
|
+
function _temp(link_2) {
|
|
514
|
+
return { ...link_2 };
|
|
515
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Resolves opt-in persistence after hydration, without changing controlled state. */
|
|
2
|
+
export declare function useSidebarPersistence(storageKey?: string): boolean | null;
|
|
3
|
+
/** Stores an optional preference while retaining usable navigation in private mode. */
|
|
4
|
+
export declare function saveSidebarPreference(storageKey: string | undefined, open: boolean): void;
|
|
5
|
+
/** Writes the cookie that server entrypoints read to render the sidebar in its last state. */
|
|
6
|
+
export declare function saveSidebarCookie(open: boolean, cookieName?: string, maxAgeSeconds?: number): void;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { c as _c } from "react/compiler-runtime";
|
|
3
|
+
/** Keeps optional browser persistence separate from the sidebar rendering contract. */
|
|
4
|
+
import { useSyncExternalStore } from "react";
|
|
5
|
+
import { SIDEBAR_COOKIE_COLLAPSED_VALUE, SIDEBAR_COOKIE_MAX_AGE, SIDEBAR_COOKIE_NAME, SIDEBAR_COOKIE_OPEN_VALUE } from "../constants/sidebar.js";
|
|
6
|
+
/** Reads a preference without making unavailable browser storage a render failure. */
|
|
7
|
+
function readSidebarPreference(storageKey) {
|
|
8
|
+
if (!storageKey || typeof window === "undefined") return null;
|
|
9
|
+
try {
|
|
10
|
+
const value = window.localStorage.getItem(storageKey);
|
|
11
|
+
if (value === SIDEBAR_COOKIE_OPEN_VALUE) return true;
|
|
12
|
+
if (value === SIDEBAR_COOKIE_COLLAPSED_VALUE) return false;
|
|
13
|
+
} catch {}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
/** Subscribes to browser storage updates and releases the listener on unmount. */
|
|
17
|
+
function subscribeToStorage(onChange) {
|
|
18
|
+
window.addEventListener("storage", onChange);
|
|
19
|
+
return () => window.removeEventListener("storage", onChange);
|
|
20
|
+
}
|
|
21
|
+
/** Keeps the first hydrated render identical to the server-provided preference. */
|
|
22
|
+
function getServerPreference() {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
/** Resolves opt-in persistence after hydration, without changing controlled state. */
|
|
26
|
+
export function useSidebarPersistence(storageKey) {
|
|
27
|
+
const $ = _c(2);
|
|
28
|
+
let t0;
|
|
29
|
+
if ($[0] !== storageKey) {
|
|
30
|
+
t0 = () => readSidebarPreference(storageKey);
|
|
31
|
+
$[0] = storageKey;
|
|
32
|
+
$[1] = t0;
|
|
33
|
+
} else {
|
|
34
|
+
t0 = $[1];
|
|
35
|
+
}
|
|
36
|
+
const getSnapshot = t0;
|
|
37
|
+
return useSyncExternalStore(subscribeToStorage, getSnapshot, getServerPreference);
|
|
38
|
+
}
|
|
39
|
+
/** Stores an optional preference while retaining usable navigation in private mode. */
|
|
40
|
+
export function saveSidebarPreference(storageKey, open) {
|
|
41
|
+
if (!storageKey) return;
|
|
42
|
+
try {
|
|
43
|
+
window.localStorage.setItem(storageKey, open ? SIDEBAR_COOKIE_OPEN_VALUE : SIDEBAR_COOKIE_COLLAPSED_VALUE);
|
|
44
|
+
} catch {}
|
|
45
|
+
}
|
|
46
|
+
/** Writes the cookie that server entrypoints read to render the sidebar in its last state. */
|
|
47
|
+
export function saveSidebarCookie(open, cookieName = SIDEBAR_COOKIE_NAME, maxAgeSeconds = SIDEBAR_COOKIE_MAX_AGE) {
|
|
48
|
+
const value = open ? SIDEBAR_COOKIE_OPEN_VALUE : SIDEBAR_COOKIE_COLLAPSED_VALUE;
|
|
49
|
+
try {
|
|
50
|
+
document.cookie = `${cookieName}=${value}; path=/; max-age=${maxAgeSeconds}; SameSite=Lax`;
|
|
51
|
+
} catch {}
|
|
52
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arc's `useToday`: the viewer's local date at midnight. It is `undefined` while rendering on the server and during
|
|
3
|
+
* hydration, so markup never depends on the server clock, and it moves to the next day when the viewer's midnight
|
|
4
|
+
* passes. The same `Date` instance is returned until the day changes.
|
|
5
|
+
* @returns Today at 00:00 in the viewer's time zone, or `undefined` before hydration.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useToday(): Date | undefined;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { c as _c } from "react/compiler-runtime";
|
|
3
|
+
/** The viewer's local date, kept out of server and hydration renders and refreshed at midnight. */
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { useIsHydrated } from "./use-is-hydrated.js";
|
|
6
|
+
/**
|
|
7
|
+
* Midnight that starts the viewer's current local day.
|
|
8
|
+
* @returns Today at 00:00 in the viewer's time zone.
|
|
9
|
+
*/
|
|
10
|
+
function startOfLocalToday() {
|
|
11
|
+
const now = new Date();
|
|
12
|
+
return new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Milliseconds until the next local midnight, measured from now.
|
|
16
|
+
* @param today - Start of the current local day.
|
|
17
|
+
* @returns The delay before the day changes.
|
|
18
|
+
*/
|
|
19
|
+
function getDelayUntilNextDay(today) {
|
|
20
|
+
const nextDay = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
|
|
21
|
+
return Math.max(0, nextDay.getTime() - Date.now());
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Arc's `useToday`: the viewer's local date at midnight. It is `undefined` while rendering on the server and during
|
|
25
|
+
* hydration, so markup never depends on the server clock, and it moves to the next day when the viewer's midnight
|
|
26
|
+
* passes. The same `Date` instance is returned until the day changes.
|
|
27
|
+
* @returns Today at 00:00 in the viewer's time zone, or `undefined` before hydration.
|
|
28
|
+
*/
|
|
29
|
+
export function useToday() {
|
|
30
|
+
const $ = _c(3);
|
|
31
|
+
const isHydrated = useIsHydrated();
|
|
32
|
+
const [today, setToday] = useState(startOfLocalToday);
|
|
33
|
+
let t0;
|
|
34
|
+
let t1;
|
|
35
|
+
if ($[0] !== today) {
|
|
36
|
+
t0 = () => {
|
|
37
|
+
const timeout = window.setTimeout(() => setToday(startOfLocalToday()), getDelayUntilNextDay(today));
|
|
38
|
+
return () => window.clearTimeout(timeout);
|
|
39
|
+
};
|
|
40
|
+
t1 = [today];
|
|
41
|
+
$[0] = today;
|
|
42
|
+
$[1] = t0;
|
|
43
|
+
$[2] = t1;
|
|
44
|
+
} else {
|
|
45
|
+
t0 = $[1];
|
|
46
|
+
t1 = $[2];
|
|
47
|
+
}
|
|
48
|
+
useEffect(t0, t1);
|
|
49
|
+
return isHydrated ? today : undefined;
|
|
50
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IANA time zone of the browser (for example "Europe/Madrid"). Returns null on
|
|
3
|
+
* the server and during hydration so zone-dependent copy never causes a
|
|
4
|
+
* markup mismatch; it settles right after hydration without an effect.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useViewerTimeZone(): string | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/** Reads the viewer IANA time zone once hydrated, so zone-dependent copy never mismatches. */
|
|
3
|
+
import { useSyncExternalStore } from "react";
|
|
4
|
+
function subscribeToNothing() {
|
|
5
|
+
return () => undefined;
|
|
6
|
+
}
|
|
7
|
+
function getViewerTimeZoneSnapshot() {
|
|
8
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
9
|
+
}
|
|
10
|
+
function getServerViewerTimeZoneSnapshot() {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* IANA time zone of the browser (for example "Europe/Madrid"). Returns null on
|
|
15
|
+
* the server and during hydration so zone-dependent copy never causes a
|
|
16
|
+
* markup mismatch; it settles right after hydration without an effect.
|
|
17
|
+
*/
|
|
18
|
+
export function useViewerTimeZone() {
|
|
19
|
+
return useSyncExternalStore(subscribeToNothing, getViewerTimeZoneSnapshot, getServerViewerTimeZoneSnapshot);
|
|
20
|
+
}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* General-purpose React hooks, published at `@astra-kit/ui/hooks` so the component barrel stays focused
|
|
3
|
+
* on UI. `useIsMobile` is also exported from the package root for existing consumers.
|
|
4
|
+
*/
|
|
5
|
+
export { useIsMobile } from "./hooks/use-mobile.js";
|
|
6
|
+
export { useIsHydrated } from "./hooks/use-is-hydrated.js";
|
|
7
|
+
export { useToday } from "./hooks/use-today.js";
|
|
8
|
+
export { usePrefersReducedMotion } from "./hooks/use-prefers-reduced-motion.js";
|
|
9
|
+
export { useViewerTimeZone } from "./hooks/use-viewer-time-zone.js";
|
|
10
|
+
export { useHorizontalSwipe, type HorizontalSwipeHandlers } from "./hooks/use-horizontal-swipe.js";
|
|
11
|
+
export { HORIZONTAL_SWIPE_DIRECTION, resolveHorizontalSwipe, type HorizontalSwipeDirection, type HorizontalSwipeGesture, } from "./lib/horizontal-swipe.js";
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* General-purpose React hooks, published at `@astra-kit/ui/hooks` so the component barrel stays focused
|
|
3
|
+
* on UI. `useIsMobile` is also exported from the package root for existing consumers.
|
|
4
|
+
*/
|
|
5
|
+
export { useIsMobile } from "./hooks/use-mobile.js";
|
|
6
|
+
export { useIsHydrated } from "./hooks/use-is-hydrated.js";
|
|
7
|
+
export { useToday } from "./hooks/use-today.js";
|
|
8
|
+
export { usePrefersReducedMotion } from "./hooks/use-prefers-reduced-motion.js";
|
|
9
|
+
export { useViewerTimeZone } from "./hooks/use-viewer-time-zone.js";
|
|
10
|
+
export { useHorizontalSwipe } from "./hooks/use-horizontal-swipe.js";
|
|
11
|
+
export { HORIZONTAL_SWIPE_DIRECTION, resolveHorizontalSwipe } from "./lib/horizontal-swipe.js";
|