@sevenfold/setto-client 0.2.3 → 0.2.6
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 +1 -1
- package/dist/edit-mode/link-action-chip.d.ts +11 -0
- package/dist/lib/link-context.d.ts +4 -0
- package/dist/lib/place-caret-at-point.d.ts +2 -0
- package/dist/lib/use-coarse-pointer.d.ts +2 -0
- package/dist/setto-client.js +215 -57
- package/dist/setto-client.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -137,7 +137,7 @@ The `/admin` dashboard does **not** activate edit mode. Use **Begynn å redigere
|
|
|
137
137
|
|--------|-----|
|
|
138
138
|
| Edit text | Click any `<T>` element — it becomes `contentEditable` |
|
|
139
139
|
| Edit section colours | Click a section or block background (not text) |
|
|
140
|
-
| Follow a link | Ctrl/Cmd + click
|
|
140
|
+
| Follow a link | Ctrl/Cmd + click (desktop) · **Naviger ↗** chip when focused (touch) |
|
|
141
141
|
| Publish | Top toolbar → **Publiser** |
|
|
142
142
|
| Exit | Top toolbar → **Avslutt** (removes `?setto=edit`) |
|
|
143
143
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
interface LinkActionChipProps {
|
|
3
|
+
anchorRef: RefObject<HTMLElement | null>;
|
|
4
|
+
visible: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Touch-only chip shown when editable link/button text is focused.
|
|
8
|
+
* Replaces Ctrl/Cmd+click on coarse-pointer devices.
|
|
9
|
+
*/
|
|
10
|
+
export declare function LinkActionChip({ anchorRef, visible }: LinkActionChipProps): import("react").ReactPortal | null;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Editable text inside a navigation target (link or button), excluding language toggles. */
|
|
2
|
+
export declare function isLinkContext(el: HTMLElement): boolean;
|
|
3
|
+
/** Same as Ctrl/Cmd+click — follow the parent link or trigger the parent button. */
|
|
4
|
+
export declare function activateLinkContext(el: HTMLElement): void;
|
package/dist/setto-client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState, useRef, useLayoutEffect, createContext, useContext, useCallback, useMemo, useId,
|
|
2
|
+
import { useEffect, useSyncExternalStore, useState, useRef, useLayoutEffect, createContext, useContext, useCallback, useMemo, useId, forwardRef } from "react";
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
5
|
function __rest(s, e) {
|
|
@@ -20987,6 +20987,7 @@ function useSettoDocumentLayout(active) {
|
|
|
20987
20987
|
html.setto-edit-mode #root {
|
|
20988
20988
|
width: 100%;
|
|
20989
20989
|
min-height: calc(100dvh - var(--setto-toolbar-height));
|
|
20990
|
+
/* Containing block for position:fixed descendants so they sit below the toolbar. */
|
|
20990
20991
|
transform: translateZ(0);
|
|
20991
20992
|
}
|
|
20992
20993
|
|
|
@@ -21006,6 +21007,10 @@ function useSettoDocumentLayout(active) {
|
|
|
21006
21007
|
z-index: 2147483645;
|
|
21007
21008
|
}
|
|
21008
21009
|
|
|
21010
|
+
html.setto-edit-mode #setto-hint-root [data-setto-ui] {
|
|
21011
|
+
pointer-events: auto;
|
|
21012
|
+
}
|
|
21013
|
+
|
|
21009
21014
|
html.setto-edit-mode #setto-section-toolbar-root {
|
|
21010
21015
|
position: fixed;
|
|
21011
21016
|
inset: 0;
|
|
@@ -21049,43 +21054,68 @@ function notifyLayoutChange() {
|
|
|
21049
21054
|
window.dispatchEvent(new Event("resize"));
|
|
21050
21055
|
});
|
|
21051
21056
|
}
|
|
21052
|
-
|
|
21053
|
-
const
|
|
21057
|
+
function isLinkContext(el) {
|
|
21058
|
+
const key = el.getAttribute("data-setto-key");
|
|
21059
|
+
if (key?.startsWith("lang.")) return false;
|
|
21060
|
+
if (el.closest("[data-setto-no-hint]")) return false;
|
|
21061
|
+
return !!(el.closest("a[href]") || el.closest("button"));
|
|
21062
|
+
}
|
|
21063
|
+
function activateLinkContext(el) {
|
|
21064
|
+
const anchor = el.closest("a[href]");
|
|
21065
|
+
if (anchor instanceof HTMLAnchorElement) {
|
|
21066
|
+
anchor.click();
|
|
21067
|
+
return;
|
|
21068
|
+
}
|
|
21069
|
+
const button = el.closest("button");
|
|
21070
|
+
if (button instanceof HTMLButtonElement) {
|
|
21071
|
+
button.click();
|
|
21072
|
+
}
|
|
21073
|
+
}
|
|
21074
|
+
const QUERY = "(hover: none) and (pointer: coarse)";
|
|
21075
|
+
function subscribe(onChange) {
|
|
21076
|
+
const mq = window.matchMedia(QUERY);
|
|
21077
|
+
mq.addEventListener("change", onChange);
|
|
21078
|
+
return () => mq.removeEventListener("change", onChange);
|
|
21079
|
+
}
|
|
21080
|
+
function getSnapshot() {
|
|
21081
|
+
return window.matchMedia(QUERY).matches;
|
|
21082
|
+
}
|
|
21083
|
+
function useCoarsePointer() {
|
|
21084
|
+
return useSyncExternalStore(subscribe, getSnapshot, () => false);
|
|
21085
|
+
}
|
|
21086
|
+
const MARGIN$2 = 10;
|
|
21087
|
+
const OFFSET$1 = 14;
|
|
21054
21088
|
function hintLabel() {
|
|
21055
21089
|
const isMac = navigator.platform.toUpperCase().includes("MAC");
|
|
21056
21090
|
return isMac ? "⌘+klikk for å åpne" : "Ctrl+klikk for å åpne";
|
|
21057
21091
|
}
|
|
21058
|
-
function isActionContext(editable) {
|
|
21059
|
-
const key = editable.getAttribute("data-setto-key");
|
|
21060
|
-
if (key?.startsWith("lang.")) return false;
|
|
21061
|
-
if (editable.closest("[data-setto-no-hint]")) return false;
|
|
21062
|
-
return !!(editable.closest("a[href]") || editable.closest("button"));
|
|
21063
|
-
}
|
|
21064
21092
|
function placeTooltip(anchor, width, height) {
|
|
21065
21093
|
const vw = window.innerWidth;
|
|
21066
21094
|
const vh = window.innerHeight;
|
|
21067
|
-
let left = anchor.x + OFFSET;
|
|
21068
|
-
let top = anchor.y + OFFSET;
|
|
21069
|
-
if (left + width > vw - MARGIN$
|
|
21070
|
-
left = anchor.x - width - OFFSET;
|
|
21095
|
+
let left = anchor.x + OFFSET$1;
|
|
21096
|
+
let top = anchor.y + OFFSET$1;
|
|
21097
|
+
if (left + width > vw - MARGIN$2) {
|
|
21098
|
+
left = anchor.x - width - OFFSET$1;
|
|
21071
21099
|
}
|
|
21072
|
-
if (left < MARGIN$
|
|
21073
|
-
left = MARGIN$
|
|
21100
|
+
if (left < MARGIN$2) {
|
|
21101
|
+
left = MARGIN$2;
|
|
21074
21102
|
}
|
|
21075
|
-
if (top + height > vh - MARGIN$
|
|
21076
|
-
top = anchor.y - height - OFFSET;
|
|
21103
|
+
if (top + height > vh - MARGIN$2) {
|
|
21104
|
+
top = anchor.y - height - OFFSET$1;
|
|
21077
21105
|
}
|
|
21078
|
-
if (top < MARGIN$
|
|
21079
|
-
top = MARGIN$
|
|
21106
|
+
if (top < MARGIN$2) {
|
|
21107
|
+
top = MARGIN$2;
|
|
21080
21108
|
}
|
|
21081
21109
|
return { left, top };
|
|
21082
21110
|
}
|
|
21083
21111
|
function EditLinkHint() {
|
|
21112
|
+
const coarsePointer = useCoarsePointer();
|
|
21084
21113
|
const [anchor, setAnchor] = useState(null);
|
|
21085
21114
|
const [position, setPosition] = useState(null);
|
|
21086
21115
|
const tipRef = useRef(null);
|
|
21087
21116
|
const text = hintLabel();
|
|
21088
21117
|
useEffect(() => {
|
|
21118
|
+
if (coarsePointer) return;
|
|
21089
21119
|
const onMove = (e) => {
|
|
21090
21120
|
const target = e.target;
|
|
21091
21121
|
if (!(target instanceof Element)) {
|
|
@@ -21093,7 +21123,7 @@ function EditLinkHint() {
|
|
|
21093
21123
|
return;
|
|
21094
21124
|
}
|
|
21095
21125
|
const editable = target.closest("[data-setto-key]");
|
|
21096
|
-
if (!(editable instanceof HTMLElement) || !
|
|
21126
|
+
if (!(editable instanceof HTMLElement) || !isLinkContext(editable)) {
|
|
21097
21127
|
setAnchor(null);
|
|
21098
21128
|
return;
|
|
21099
21129
|
}
|
|
@@ -21101,7 +21131,7 @@ function EditLinkHint() {
|
|
|
21101
21131
|
};
|
|
21102
21132
|
document.addEventListener("mousemove", onMove, true);
|
|
21103
21133
|
return () => document.removeEventListener("mousemove", onMove, true);
|
|
21104
|
-
}, []);
|
|
21134
|
+
}, [coarsePointer]);
|
|
21105
21135
|
useLayoutEffect(() => {
|
|
21106
21136
|
if (!anchor || !tipRef.current) {
|
|
21107
21137
|
setPosition(null);
|
|
@@ -21110,11 +21140,11 @@ function EditLinkHint() {
|
|
|
21110
21140
|
const { width, height } = tipRef.current.getBoundingClientRect();
|
|
21111
21141
|
setPosition(placeTooltip(anchor, width, height));
|
|
21112
21142
|
}, [anchor, text]);
|
|
21113
|
-
if (!anchor) return null;
|
|
21143
|
+
if (coarsePointer || !anchor) return null;
|
|
21114
21144
|
const style = {
|
|
21115
21145
|
position: "fixed",
|
|
21116
|
-
left: position?.left ?? anchor.x + OFFSET,
|
|
21117
|
-
top: position?.top ?? anchor.y + OFFSET,
|
|
21146
|
+
left: position?.left ?? anchor.x + OFFSET$1,
|
|
21147
|
+
top: position?.top ?? anchor.y + OFFSET$1,
|
|
21118
21148
|
visibility: position ? "visible" : "hidden",
|
|
21119
21149
|
background: "#1a1a1a",
|
|
21120
21150
|
color: "#fff",
|
|
@@ -21176,11 +21206,11 @@ function useSectionEdit() {
|
|
|
21176
21206
|
}
|
|
21177
21207
|
const SECTION_TOOLBAR_HEIGHT = 44;
|
|
21178
21208
|
const GAP = 8;
|
|
21179
|
-
const MARGIN = 8;
|
|
21209
|
+
const MARGIN$1 = 8;
|
|
21180
21210
|
function computePosition(targetEl, toolbarW, toolbarH) {
|
|
21181
21211
|
const rect = targetEl.getBoundingClientRect();
|
|
21182
21212
|
let left = rect.left + (rect.width - toolbarW) / 2;
|
|
21183
|
-
left = Math.max(MARGIN, Math.min(left, window.innerWidth - toolbarW - MARGIN));
|
|
21213
|
+
left = Math.max(MARGIN$1, Math.min(left, window.innerWidth - toolbarW - MARGIN$1));
|
|
21184
21214
|
const minTop = TOOLBAR_HEIGHT + GAP;
|
|
21185
21215
|
const top = Math.max(minTop, rect.top - toolbarH - GAP);
|
|
21186
21216
|
return { top, left };
|
|
@@ -21434,7 +21464,7 @@ function SectionToolbar() {
|
|
|
21434
21464
|
top: pos?.top ?? -9999,
|
|
21435
21465
|
left: pos?.left ?? 0,
|
|
21436
21466
|
width: "max-content",
|
|
21437
|
-
maxWidth: `calc(100vw - ${MARGIN * 2}px)`,
|
|
21467
|
+
maxWidth: `calc(100vw - ${MARGIN$1 * 2}px)`,
|
|
21438
21468
|
minHeight: SECTION_TOOLBAR_HEIGHT,
|
|
21439
21469
|
zIndex: 2147483646,
|
|
21440
21470
|
display: "flex",
|
|
@@ -22442,17 +22472,127 @@ function useSetto() {
|
|
|
22442
22472
|
}
|
|
22443
22473
|
return ctx;
|
|
22444
22474
|
}
|
|
22445
|
-
|
|
22446
|
-
|
|
22447
|
-
|
|
22448
|
-
|
|
22449
|
-
|
|
22475
|
+
const MARGIN = 10;
|
|
22476
|
+
const OFFSET = 8;
|
|
22477
|
+
const MIN_TOUCH = 44;
|
|
22478
|
+
function placeChip(anchor, width, height) {
|
|
22479
|
+
const vw = window.innerWidth;
|
|
22480
|
+
const vh = window.innerHeight;
|
|
22481
|
+
let left = anchor.left + anchor.width / 2 - width / 2;
|
|
22482
|
+
let top = anchor.bottom + OFFSET;
|
|
22483
|
+
if (left + width > vw - MARGIN) left = vw - width - MARGIN;
|
|
22484
|
+
if (left < MARGIN) left = MARGIN;
|
|
22485
|
+
if (top + height > vh - MARGIN) {
|
|
22486
|
+
top = anchor.top - height - OFFSET;
|
|
22487
|
+
}
|
|
22488
|
+
if (top < MARGIN) top = MARGIN;
|
|
22489
|
+
return { left, top };
|
|
22490
|
+
}
|
|
22491
|
+
function LinkActionChip({ anchorRef, visible }) {
|
|
22492
|
+
const chipRef = useRef(null);
|
|
22493
|
+
const [position, setPosition] = useState(null);
|
|
22494
|
+
useLayoutEffect(() => {
|
|
22495
|
+
if (!visible || !anchorRef.current) {
|
|
22496
|
+
setPosition(null);
|
|
22497
|
+
return;
|
|
22498
|
+
}
|
|
22499
|
+
const update = () => {
|
|
22500
|
+
const el = anchorRef.current;
|
|
22501
|
+
const chip = chipRef.current;
|
|
22502
|
+
if (!el) return;
|
|
22503
|
+
const rect = el.getBoundingClientRect();
|
|
22504
|
+
const width = chip?.offsetWidth ?? 120;
|
|
22505
|
+
const height = chip?.offsetHeight ?? MIN_TOUCH;
|
|
22506
|
+
setPosition(placeChip(rect, width, height));
|
|
22507
|
+
};
|
|
22508
|
+
update();
|
|
22509
|
+
window.addEventListener("scroll", update, true);
|
|
22510
|
+
window.addEventListener("resize", update);
|
|
22511
|
+
return () => {
|
|
22512
|
+
window.removeEventListener("scroll", update, true);
|
|
22513
|
+
window.removeEventListener("resize", update);
|
|
22514
|
+
};
|
|
22515
|
+
}, [visible, anchorRef]);
|
|
22516
|
+
if (!visible || !anchorRef.current) return null;
|
|
22517
|
+
const host = document.getElementById("setto-hint-root") ?? document.body;
|
|
22518
|
+
const style = {
|
|
22519
|
+
position: "fixed",
|
|
22520
|
+
left: position?.left ?? 0,
|
|
22521
|
+
top: position?.top ?? 0,
|
|
22522
|
+
visibility: position ? "visible" : "hidden",
|
|
22523
|
+
minHeight: MIN_TOUCH,
|
|
22524
|
+
minWidth: MIN_TOUCH,
|
|
22525
|
+
padding: "10px 14px",
|
|
22526
|
+
background: "#1a1a1a",
|
|
22527
|
+
color: "#fff",
|
|
22528
|
+
fontSize: 13,
|
|
22529
|
+
fontWeight: 500,
|
|
22530
|
+
border: "none",
|
|
22531
|
+
borderRadius: 8,
|
|
22532
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.2)",
|
|
22533
|
+
fontFamily: "system-ui, sans-serif",
|
|
22534
|
+
whiteSpace: "nowrap",
|
|
22535
|
+
touchAction: "manipulation",
|
|
22536
|
+
zIndex: 2147483647
|
|
22537
|
+
};
|
|
22538
|
+
return createPortal(
|
|
22539
|
+
/* @__PURE__ */ jsx(
|
|
22540
|
+
"button",
|
|
22541
|
+
{
|
|
22542
|
+
ref: chipRef,
|
|
22543
|
+
type: "button",
|
|
22544
|
+
"data-setto-ui": true,
|
|
22545
|
+
style,
|
|
22546
|
+
onMouseDown: (e) => {
|
|
22547
|
+
e.preventDefault();
|
|
22548
|
+
e.stopPropagation();
|
|
22549
|
+
},
|
|
22550
|
+
onClick: (e) => {
|
|
22551
|
+
e.preventDefault();
|
|
22552
|
+
e.stopPropagation();
|
|
22553
|
+
const el = anchorRef.current;
|
|
22554
|
+
if (el) activateLinkContext(el);
|
|
22555
|
+
el?.blur();
|
|
22556
|
+
},
|
|
22557
|
+
children: "Naviger ↗"
|
|
22558
|
+
}
|
|
22559
|
+
),
|
|
22560
|
+
host
|
|
22561
|
+
);
|
|
22562
|
+
}
|
|
22563
|
+
function placeCaretAtPoint(x, y, el) {
|
|
22564
|
+
el.focus();
|
|
22565
|
+
const doc = el.ownerDocument;
|
|
22566
|
+
const selection = doc.getSelection();
|
|
22567
|
+
if (!selection) return;
|
|
22568
|
+
const range = rangeFromPoint(doc, x, y);
|
|
22569
|
+
if (!range) return;
|
|
22570
|
+
if (!el.contains(range.startContainer)) {
|
|
22571
|
+
range.selectNodeContents(el);
|
|
22572
|
+
range.collapse(false);
|
|
22573
|
+
}
|
|
22574
|
+
selection.removeAllRanges();
|
|
22575
|
+
selection.addRange(range);
|
|
22576
|
+
}
|
|
22577
|
+
function rangeFromPoint(doc, x, y) {
|
|
22578
|
+
if (doc.caretRangeFromPoint) {
|
|
22579
|
+
return doc.caretRangeFromPoint(x, y);
|
|
22580
|
+
}
|
|
22581
|
+
const legacy = doc;
|
|
22582
|
+
const pos = legacy.caretPositionFromPoint?.(x, y);
|
|
22583
|
+
if (!pos) return null;
|
|
22584
|
+
const range = doc.createRange();
|
|
22585
|
+
range.setStart(pos.offsetNode, pos.offset);
|
|
22586
|
+
range.collapse(true);
|
|
22587
|
+
return range;
|
|
22450
22588
|
}
|
|
22451
22589
|
function T({ k }) {
|
|
22452
22590
|
const { t, i18n } = useTranslation();
|
|
22453
22591
|
const { editMode, store } = useSetto();
|
|
22454
22592
|
const ref = useRef(null);
|
|
22455
22593
|
const [focused, setFocused] = useState(false);
|
|
22594
|
+
const [linkContext, setLinkContext] = useState(false);
|
|
22595
|
+
const coarsePointer = useCoarsePointer();
|
|
22456
22596
|
const [, force] = useState(0);
|
|
22457
22597
|
useEffect(() => {
|
|
22458
22598
|
if (!store) return;
|
|
@@ -22472,6 +22612,15 @@ function T({ k }) {
|
|
|
22472
22612
|
if (e.ctrlKey || e.metaKey) return;
|
|
22473
22613
|
e.preventDefault();
|
|
22474
22614
|
};
|
|
22615
|
+
const handleMouseUp = (e) => {
|
|
22616
|
+
if (e.button !== 0) return;
|
|
22617
|
+
e.stopPropagation();
|
|
22618
|
+
const el = e.currentTarget;
|
|
22619
|
+
if (isLinkContext(el) && (e.ctrlKey || e.metaKey)) return;
|
|
22620
|
+
if (isLinkContext(el)) {
|
|
22621
|
+
placeCaretAtPoint(e.clientX, e.clientY, el);
|
|
22622
|
+
}
|
|
22623
|
+
};
|
|
22475
22624
|
const handleClick = (e) => {
|
|
22476
22625
|
e.stopPropagation();
|
|
22477
22626
|
const el = e.currentTarget;
|
|
@@ -22479,7 +22628,6 @@ function T({ k }) {
|
|
|
22479
22628
|
if (isLinkContext(el)) {
|
|
22480
22629
|
e.preventDefault();
|
|
22481
22630
|
}
|
|
22482
|
-
el.focus();
|
|
22483
22631
|
};
|
|
22484
22632
|
const commit = (el) => {
|
|
22485
22633
|
const text = el.textContent ?? "";
|
|
@@ -22487,37 +22635,47 @@ function T({ k }) {
|
|
|
22487
22635
|
};
|
|
22488
22636
|
const handleBlur = (e) => {
|
|
22489
22637
|
setFocused(false);
|
|
22638
|
+
setLinkContext(false);
|
|
22490
22639
|
commit(e.currentTarget);
|
|
22491
22640
|
};
|
|
22492
22641
|
const handleInput = (e) => {
|
|
22493
22642
|
store?.set(k, i18n.language, e.currentTarget.textContent ?? "");
|
|
22494
22643
|
};
|
|
22495
22644
|
const lang = toBcp47(i18n.language);
|
|
22496
|
-
|
|
22497
|
-
|
|
22498
|
-
|
|
22499
|
-
|
|
22500
|
-
|
|
22501
|
-
|
|
22502
|
-
|
|
22503
|
-
|
|
22504
|
-
|
|
22505
|
-
|
|
22506
|
-
|
|
22507
|
-
|
|
22508
|
-
|
|
22509
|
-
|
|
22510
|
-
|
|
22511
|
-
|
|
22512
|
-
|
|
22513
|
-
|
|
22514
|
-
|
|
22515
|
-
|
|
22516
|
-
|
|
22517
|
-
|
|
22645
|
+
const showLinkChip = coarsePointer && focused && linkContext;
|
|
22646
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
22647
|
+
/* @__PURE__ */ jsx(
|
|
22648
|
+
"span",
|
|
22649
|
+
{
|
|
22650
|
+
ref,
|
|
22651
|
+
"data-setto-key": k,
|
|
22652
|
+
contentEditable: true,
|
|
22653
|
+
suppressContentEditableWarning: true,
|
|
22654
|
+
lang,
|
|
22655
|
+
spellCheck: true,
|
|
22656
|
+
role: "textbox",
|
|
22657
|
+
tabIndex: 0,
|
|
22658
|
+
onFocus: (e) => {
|
|
22659
|
+
setFocused(true);
|
|
22660
|
+
setLinkContext(isLinkContext(e.currentTarget));
|
|
22661
|
+
},
|
|
22662
|
+
onBlur: handleBlur,
|
|
22663
|
+
onInput: handleInput,
|
|
22664
|
+
onMouseDown: handleMouseDown,
|
|
22665
|
+
onMouseUp: handleMouseUp,
|
|
22666
|
+
onClick: handleClick,
|
|
22667
|
+
style: {
|
|
22668
|
+
cursor: "text",
|
|
22669
|
+
color: "inherit",
|
|
22670
|
+
outline: focused ? "2px solid #640AFF" : void 0,
|
|
22671
|
+
outlineOffset: 2,
|
|
22672
|
+
borderRadius: 2,
|
|
22673
|
+
transition: "outline-color 120ms"
|
|
22674
|
+
}
|
|
22518
22675
|
}
|
|
22519
|
-
|
|
22520
|
-
|
|
22676
|
+
),
|
|
22677
|
+
showLinkChip ? /* @__PURE__ */ jsx(LinkActionChip, { anchorRef: ref, visible: focused }) : null
|
|
22678
|
+
] });
|
|
22521
22679
|
}
|
|
22522
22680
|
function toBcp47(code) {
|
|
22523
22681
|
const base = (code.split("-")[0] ?? code).toLowerCase();
|