@refraction-ui/react 0.16.1 → 0.17.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/dist/index.cjs +2050 -436
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2047 -432
- package/dist/index.js.map +1 -1
- package/dist/internal/composer/index.d.ts +590 -0
- package/dist/internal/date-picker/index.d.cts +3 -1
- package/dist/internal/date-picker/index.d.ts +3 -1
- package/dist/internal/react-composer/index.d.ts +131 -0
- package/dist/internal/react-date-picker/index.d.cts +2 -10
- package/dist/internal/react-date-picker/index.d.ts +2 -10
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { cn, devWarn, cva, createKeyboardHandler, Keys, createMachine
|
|
2
|
+
import { cn, devWarn, cva, generateId, createKeyboardHandler, Keys, createMachine } from './chunk-VZLV27H2.js';
|
|
3
3
|
export { createFaroSink } from './chunk-XWP763SH.js';
|
|
4
4
|
import * as React11 from 'react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -1140,14 +1140,14 @@ function createCalendar(props = {}) {
|
|
|
1140
1140
|
const gridId = generateId("rfr-calendar");
|
|
1141
1141
|
const labelId = generateId("rfr-calendar-label");
|
|
1142
1142
|
function isDateDisabled(date) {
|
|
1143
|
-
if (minDate && date <
|
|
1144
|
-
if (maxDate && date >
|
|
1143
|
+
if (minDate && date < startOfDay(minDate)) return true;
|
|
1144
|
+
if (maxDate && date > endOfDay(maxDate)) return true;
|
|
1145
1145
|
return disabledDates.some((d) => isSameDay(d, date));
|
|
1146
1146
|
}
|
|
1147
|
-
function
|
|
1147
|
+
function startOfDay(date) {
|
|
1148
1148
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
1149
1149
|
}
|
|
1150
|
-
function
|
|
1150
|
+
function endOfDay(date) {
|
|
1151
1151
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
|
|
1152
1152
|
}
|
|
1153
1153
|
function buildDays() {
|
|
@@ -2679,18 +2679,2001 @@ var CommandItem = React11.forwardRef(
|
|
|
2679
2679
|
);
|
|
2680
2680
|
}
|
|
2681
2681
|
);
|
|
2682
|
-
CommandItem.displayName = "CommandItem";
|
|
2683
|
-
var CommandSeparator = React11.forwardRef(
|
|
2684
|
-
({ className, ...props }, ref) => {
|
|
2685
|
-
return React11.createElement("div", {
|
|
2686
|
-
ref,
|
|
2687
|
-
role: "separator",
|
|
2688
|
-
className: cn("-mx-1 h-px bg-border", className),
|
|
2689
|
-
...props
|
|
2690
|
-
});
|
|
2691
|
-
}
|
|
2692
|
-
);
|
|
2693
|
-
CommandSeparator.displayName = "CommandSeparator";
|
|
2682
|
+
CommandItem.displayName = "CommandItem";
|
|
2683
|
+
var CommandSeparator = React11.forwardRef(
|
|
2684
|
+
({ className, ...props }, ref) => {
|
|
2685
|
+
return React11.createElement("div", {
|
|
2686
|
+
ref,
|
|
2687
|
+
role: "separator",
|
|
2688
|
+
className: cn("-mx-1 h-px bg-border", className),
|
|
2689
|
+
...props
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
);
|
|
2693
|
+
CommandSeparator.displayName = "CommandSeparator";
|
|
2694
|
+
function detectTriggerInText(text, caret, triggerChar) {
|
|
2695
|
+
if (triggerChar.length === 0) return null;
|
|
2696
|
+
const before = text.slice(0, caret);
|
|
2697
|
+
const idx = before.lastIndexOf(triggerChar);
|
|
2698
|
+
if (idx === -1) return null;
|
|
2699
|
+
if (idx > 0 && !/\s/.test(before[idx - 1])) return null;
|
|
2700
|
+
const query = before.slice(idx + triggerChar.length);
|
|
2701
|
+
if (/\s/.test(query)) return null;
|
|
2702
|
+
return { triggered: true, query, start: idx };
|
|
2703
|
+
}
|
|
2704
|
+
var EMOJI_MAP = {
|
|
2705
|
+
":smile:": "\u{1F604}",
|
|
2706
|
+
":laugh:": "\u{1F602}",
|
|
2707
|
+
":joy:": "\u{1F602}",
|
|
2708
|
+
":grin:": "\u{1F601}",
|
|
2709
|
+
":wink:": "\u{1F609}",
|
|
2710
|
+
":blush:": "\u{1F60A}",
|
|
2711
|
+
":heart_eyes:": "\u{1F60D}",
|
|
2712
|
+
":kissing:": "\u{1F617}",
|
|
2713
|
+
":thinking:": "\u{1F914}",
|
|
2714
|
+
":neutral:": "\u{1F610}",
|
|
2715
|
+
":expressionless:": "\u{1F611}",
|
|
2716
|
+
":unamused:": "\u{1F612}",
|
|
2717
|
+
":sweat:": "\u{1F613}",
|
|
2718
|
+
":pensive:": "\u{1F614}",
|
|
2719
|
+
":confused:": "\u{1F615}",
|
|
2720
|
+
":disappointed:": "\u{1F61E}",
|
|
2721
|
+
":worried:": "\u{1F61F}",
|
|
2722
|
+
":angry:": "\u{1F620}",
|
|
2723
|
+
":rage:": "\u{1F621}",
|
|
2724
|
+
":cry:": "\u{1F622}",
|
|
2725
|
+
":sob:": "\u{1F62D}",
|
|
2726
|
+
":scream:": "\u{1F631}",
|
|
2727
|
+
":fearful:": "\u{1F628}",
|
|
2728
|
+
":cold_sweat:": "\u{1F630}",
|
|
2729
|
+
":relieved:": "\u{1F60C}",
|
|
2730
|
+
":sleepy:": "\u{1F62A}",
|
|
2731
|
+
":sleeping:": "\u{1F634}",
|
|
2732
|
+
":mask:": "\u{1F637}",
|
|
2733
|
+
":sunglasses:": "\u{1F60E}",
|
|
2734
|
+
":nerd:": "\u{1F913}",
|
|
2735
|
+
":heart:": "\u2764\uFE0F",
|
|
2736
|
+
":broken_heart:": "\u{1F494}",
|
|
2737
|
+
":sparkling_heart:": "\u{1F496}",
|
|
2738
|
+
":two_hearts:": "\u{1F495}",
|
|
2739
|
+
":fire:": "\u{1F525}",
|
|
2740
|
+
":100:": "\u{1F4AF}",
|
|
2741
|
+
":star:": "\u2B50",
|
|
2742
|
+
":star2:": "\u{1F31F}",
|
|
2743
|
+
":sparkles:": "\u2728",
|
|
2744
|
+
":thumbsup:": "\u{1F44D}",
|
|
2745
|
+
":thumbsdown:": "\u{1F44E}",
|
|
2746
|
+
":wave:": "\u{1F44B}",
|
|
2747
|
+
":clap:": "\u{1F44F}",
|
|
2748
|
+
":raised_hands:": "\u{1F64C}",
|
|
2749
|
+
":pray:": "\u{1F64F}",
|
|
2750
|
+
":muscle:": "\u{1F4AA}",
|
|
2751
|
+
":point_up:": "\u261D\uFE0F",
|
|
2752
|
+
":point_down:": "\u{1F447}",
|
|
2753
|
+
":point_left:": "\u{1F448}",
|
|
2754
|
+
":point_right:": "\u{1F449}",
|
|
2755
|
+
":ok_hand:": "\u{1F44C}",
|
|
2756
|
+
":v:": "\u270C\uFE0F",
|
|
2757
|
+
":eyes:": "\u{1F440}",
|
|
2758
|
+
":tongue:": "\u{1F445}",
|
|
2759
|
+
":lips:": "\u{1F444}",
|
|
2760
|
+
":rocket:": "\u{1F680}",
|
|
2761
|
+
":tada:": "\u{1F389}",
|
|
2762
|
+
":confetti:": "\u{1F38A}",
|
|
2763
|
+
":balloon:": "\u{1F388}",
|
|
2764
|
+
":gift:": "\u{1F381}",
|
|
2765
|
+
":trophy:": "\u{1F3C6}",
|
|
2766
|
+
":medal:": "\u{1F3C5}",
|
|
2767
|
+
":crown:": "\u{1F451}",
|
|
2768
|
+
":gem:": "\u{1F48E}",
|
|
2769
|
+
":bell:": "\u{1F514}",
|
|
2770
|
+
":check:": "\u2705",
|
|
2771
|
+
":x:": "\u274C",
|
|
2772
|
+
":warning:": "\u26A0\uFE0F",
|
|
2773
|
+
":no_entry:": "\u26D4",
|
|
2774
|
+
":question:": "\u2753",
|
|
2775
|
+
":exclamation:": "\u2757",
|
|
2776
|
+
":bulb:": "\u{1F4A1}",
|
|
2777
|
+
":book:": "\u{1F4D6}",
|
|
2778
|
+
":memo:": "\u{1F4DD}",
|
|
2779
|
+
":pencil:": "\u270F\uFE0F",
|
|
2780
|
+
":calendar:": "\u{1F4C5}",
|
|
2781
|
+
":clock:": "\u{1F550}",
|
|
2782
|
+
":hourglass:": "\u231B",
|
|
2783
|
+
":lock:": "\u{1F512}",
|
|
2784
|
+
":key:": "\u{1F511}",
|
|
2785
|
+
":hammer:": "\u{1F528}",
|
|
2786
|
+
":wrench:": "\u{1F527}",
|
|
2787
|
+
":link:": "\u{1F517}",
|
|
2788
|
+
":paperclip:": "\u{1F4CE}",
|
|
2789
|
+
":scissors:": "\u2702\uFE0F",
|
|
2790
|
+
":package:": "\u{1F4E6}",
|
|
2791
|
+
":email:": "\u{1F4E7}",
|
|
2792
|
+
":phone:": "\u{1F4DE}",
|
|
2793
|
+
":computer:": "\u{1F4BB}",
|
|
2794
|
+
":house:": "\u{1F3E0}",
|
|
2795
|
+
":tree:": "\u{1F333}",
|
|
2796
|
+
":sun:": "\u2600\uFE0F",
|
|
2797
|
+
":moon:": "\u{1F319}",
|
|
2798
|
+
":cloud:": "\u2601\uFE0F",
|
|
2799
|
+
":rain:": "\u{1F327}\uFE0F",
|
|
2800
|
+
":snow:": "\u2744\uFE0F",
|
|
2801
|
+
":zap:": "\u26A1",
|
|
2802
|
+
":rainbow:": "\u{1F308}",
|
|
2803
|
+
":pizza:": "\u{1F355}",
|
|
2804
|
+
":hamburger:": "\u{1F354}",
|
|
2805
|
+
":coffee:": "\u2615",
|
|
2806
|
+
":beer:": "\u{1F37A}",
|
|
2807
|
+
":wine:": "\u{1F377}",
|
|
2808
|
+
":cake:": "\u{1F370}",
|
|
2809
|
+
":dog:": "\u{1F436}",
|
|
2810
|
+
":cat:": "\u{1F431}",
|
|
2811
|
+
":poop:": "\u{1F4A9}",
|
|
2812
|
+
":ghost:": "\u{1F47B}",
|
|
2813
|
+
":skull:": "\u{1F480}",
|
|
2814
|
+
":alien:": "\u{1F47D}",
|
|
2815
|
+
":robot:": "\u{1F916}",
|
|
2816
|
+
":handshake:": "\u{1F91D}",
|
|
2817
|
+
":pray2:": "\u{1F64F}",
|
|
2818
|
+
":salute:": "\u{1FAE1}"
|
|
2819
|
+
};
|
|
2820
|
+
function detectEmojiShortcode(text) {
|
|
2821
|
+
const match = text.match(/:([a-z0-9_]+):$/);
|
|
2822
|
+
if (!match) return null;
|
|
2823
|
+
const shortcode = `:${match[1]}:`;
|
|
2824
|
+
const unicode = EMOJI_MAP[shortcode];
|
|
2825
|
+
if (!unicode) return null;
|
|
2826
|
+
return { shortcode, unicode };
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
// ../composer/dist/index.js
|
|
2830
|
+
function toMessageAttachment(attachment) {
|
|
2831
|
+
return {
|
|
2832
|
+
id: attachment.id,
|
|
2833
|
+
name: attachment.name,
|
|
2834
|
+
url: attachment.previewUrl ?? "",
|
|
2835
|
+
type: attachment.mimeType ?? attachment.kind,
|
|
2836
|
+
size: attachment.sizeBytes
|
|
2837
|
+
};
|
|
2838
|
+
}
|
|
2839
|
+
var cachedSegmenter;
|
|
2840
|
+
function getSegmenter() {
|
|
2841
|
+
if (cachedSegmenter === void 0) {
|
|
2842
|
+
const IntlAny = typeof Intl !== "undefined" ? Intl : void 0;
|
|
2843
|
+
const Segmenter = IntlAny?.Segmenter;
|
|
2844
|
+
cachedSegmenter = Segmenter ? new Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
2845
|
+
}
|
|
2846
|
+
return cachedSegmenter;
|
|
2847
|
+
}
|
|
2848
|
+
function isHighSurrogate(code) {
|
|
2849
|
+
return code >= 55296 && code <= 56319;
|
|
2850
|
+
}
|
|
2851
|
+
function isLowSurrogate(code) {
|
|
2852
|
+
return code >= 56320 && code <= 57343;
|
|
2853
|
+
}
|
|
2854
|
+
function graphemeLength(text) {
|
|
2855
|
+
if (text === "") return 0;
|
|
2856
|
+
const segmenter = getSegmenter();
|
|
2857
|
+
if (segmenter) {
|
|
2858
|
+
let count2 = 0;
|
|
2859
|
+
for (const _ of segmenter.segment(text)) count2++;
|
|
2860
|
+
return count2;
|
|
2861
|
+
}
|
|
2862
|
+
let count = 0;
|
|
2863
|
+
for (const _ of text) count++;
|
|
2864
|
+
return count;
|
|
2865
|
+
}
|
|
2866
|
+
function clampGraphemes(text, max) {
|
|
2867
|
+
if (max <= 0) return "";
|
|
2868
|
+
const segmenter = getSegmenter();
|
|
2869
|
+
if (segmenter) {
|
|
2870
|
+
let count2 = 0;
|
|
2871
|
+
let endIndex = text.length;
|
|
2872
|
+
for (const part of segmenter.segment(text)) {
|
|
2873
|
+
count2++;
|
|
2874
|
+
if (count2 > max) {
|
|
2875
|
+
endIndex = part.index;
|
|
2876
|
+
break;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
return text.slice(0, endIndex);
|
|
2880
|
+
}
|
|
2881
|
+
let count = 0;
|
|
2882
|
+
let i = 0;
|
|
2883
|
+
while (i < text.length && count < max) {
|
|
2884
|
+
const code = text.charCodeAt(i);
|
|
2885
|
+
i += isHighSurrogate(code) && i + 1 < text.length && isLowSurrogate(text.charCodeAt(i + 1)) ? 2 : 1;
|
|
2886
|
+
count++;
|
|
2887
|
+
}
|
|
2888
|
+
return text.slice(0, i);
|
|
2889
|
+
}
|
|
2890
|
+
function payloadFor(raw) {
|
|
2891
|
+
return raw.trim();
|
|
2892
|
+
}
|
|
2893
|
+
function canSend({ text, attachments = [], disabled = false, readOnly = false, busy = false }) {
|
|
2894
|
+
if (disabled || readOnly || busy) return false;
|
|
2895
|
+
return payloadFor(text).length > 0 || attachments.length > 0;
|
|
2896
|
+
}
|
|
2897
|
+
function shouldSubmitOnEnter({
|
|
2898
|
+
shiftPressed,
|
|
2899
|
+
isComposing
|
|
2900
|
+
}) {
|
|
2901
|
+
return !shiftPressed && !isComposing;
|
|
2902
|
+
}
|
|
2903
|
+
var COUNTER_VISIBLE_FRACTION = 0.2;
|
|
2904
|
+
function computeCounter(text, maxLength) {
|
|
2905
|
+
if (maxLength === void 0) {
|
|
2906
|
+
return { visible: false, remaining: null, overLimit: false };
|
|
2907
|
+
}
|
|
2908
|
+
const remaining = maxLength - graphemeLength(text);
|
|
2909
|
+
return {
|
|
2910
|
+
visible: remaining <= maxLength * COUNTER_VISIBLE_FRACTION,
|
|
2911
|
+
remaining,
|
|
2912
|
+
overLimit: remaining <= 0
|
|
2913
|
+
};
|
|
2914
|
+
}
|
|
2915
|
+
var DEFAULT_MAX_QUERY_LENGTH = 40;
|
|
2916
|
+
var DEFAULT_MAX_VISIBLE_RESULTS = 6;
|
|
2917
|
+
var SCAN_UNITS_PER_GRAPHEME = 16;
|
|
2918
|
+
function resolveTriggerConfig(trigger) {
|
|
2919
|
+
const symbol = trigger.symbol;
|
|
2920
|
+
return {
|
|
2921
|
+
id: trigger.id,
|
|
2922
|
+
symbol,
|
|
2923
|
+
scope: trigger.scope ?? "anywhere",
|
|
2924
|
+
queryPattern: trigger.queryPattern ?? null,
|
|
2925
|
+
maxQueryLength: trigger.maxQueryLength ?? DEFAULT_MAX_QUERY_LENGTH,
|
|
2926
|
+
closeOnSpace: trigger.closeOnSpace ?? true,
|
|
2927
|
+
allowMidWord: trigger.allowMidWord ?? false,
|
|
2928
|
+
extraBoundaryChars: trigger.extraBoundaryChars ?? [],
|
|
2929
|
+
debounceMs: trigger.debounceMs ?? 0,
|
|
2930
|
+
maxVisibleResults: trigger.maxVisibleResults ?? DEFAULT_MAX_VISIBLE_RESULTS,
|
|
2931
|
+
wrapNavigation: trigger.wrapNavigation ?? true,
|
|
2932
|
+
toDisplay: trigger.toDisplay ?? ((candidate) => `${symbol}${candidate.display}`),
|
|
2933
|
+
resolve: trigger.resolve
|
|
2934
|
+
};
|
|
2935
|
+
}
|
|
2936
|
+
function scanWindowFor(trigger) {
|
|
2937
|
+
return trigger.maxQueryLength * SCAN_UNITS_PER_GRAPHEME + trigger.symbol.length;
|
|
2938
|
+
}
|
|
2939
|
+
function isWhitespace(ch) {
|
|
2940
|
+
return /\s/.test(ch);
|
|
2941
|
+
}
|
|
2942
|
+
function boundaryOk(text, symbolStart, trigger) {
|
|
2943
|
+
if (trigger.allowMidWord) return true;
|
|
2944
|
+
if (symbolStart === 0) return true;
|
|
2945
|
+
const prev = text[symbolStart - 1];
|
|
2946
|
+
return isWhitespace(prev) || trigger.extraBoundaryChars.includes(prev);
|
|
2947
|
+
}
|
|
2948
|
+
function scopeOk(text, symbolStart, scope) {
|
|
2949
|
+
if (scope === "anywhere") return true;
|
|
2950
|
+
if (scope === "startOfMessage") return symbolStart === 0;
|
|
2951
|
+
return symbolStart === 0 || text[symbolStart - 1] === "\n";
|
|
2952
|
+
}
|
|
2953
|
+
function findCandidate(text, caret, trigger) {
|
|
2954
|
+
const window2 = scanWindowFor(trigger);
|
|
2955
|
+
const isSimple = trigger.symbol.length === 1 && trigger.scope === "anywhere" && trigger.closeOnSpace && !trigger.allowMidWord && trigger.extraBoundaryChars.length === 0;
|
|
2956
|
+
if (isSimple) {
|
|
2957
|
+
const sliceStart2 = Math.max(0, caret - window2 - 1);
|
|
2958
|
+
const slice = text.slice(sliceStart2, caret);
|
|
2959
|
+
const hit = detectTriggerInText(slice, slice.length, trigger.symbol);
|
|
2960
|
+
if (!hit) return null;
|
|
2961
|
+
return { symbolStart: sliceStart2 + hit.start, query: hit.query };
|
|
2962
|
+
}
|
|
2963
|
+
const sliceStart = Math.max(0, caret - window2);
|
|
2964
|
+
const rel = text.slice(sliceStart, caret).lastIndexOf(trigger.symbol);
|
|
2965
|
+
if (rel === -1) return null;
|
|
2966
|
+
const symbolStart = sliceStart + rel;
|
|
2967
|
+
if (symbolStart + trigger.symbol.length > caret) return null;
|
|
2968
|
+
return { symbolStart, query: text.slice(symbolStart + trigger.symbol.length, caret) };
|
|
2969
|
+
}
|
|
2970
|
+
function validateCandidate(text, caret, trigger, candidate, dismissed, tokenRanges) {
|
|
2971
|
+
const { symbolStart, query } = candidate;
|
|
2972
|
+
if (!boundaryOk(text, symbolStart, trigger)) return null;
|
|
2973
|
+
if (!scopeOk(text, symbolStart, trigger.scope)) return null;
|
|
2974
|
+
for (const range of tokenRanges) {
|
|
2975
|
+
if (symbolStart >= range.start && symbolStart < range.end) return null;
|
|
2976
|
+
}
|
|
2977
|
+
if (dismissed.some((d) => d.triggerId === trigger.id && d.symbolStart === symbolStart)) return null;
|
|
2978
|
+
if (trigger.closeOnSpace && /\s/.test(query)) return null;
|
|
2979
|
+
if (!trigger.closeOnSpace && query.includes("\n")) return null;
|
|
2980
|
+
if (graphemeLength(query) > trigger.maxQueryLength) return null;
|
|
2981
|
+
if (trigger.queryPattern && !trigger.queryPattern.test(query)) return null;
|
|
2982
|
+
return { trigger, symbolStart, caret, query };
|
|
2983
|
+
}
|
|
2984
|
+
function detectActiveTrigger({
|
|
2985
|
+
text,
|
|
2986
|
+
caret,
|
|
2987
|
+
triggers,
|
|
2988
|
+
isComposing = false,
|
|
2989
|
+
dismissed = [],
|
|
2990
|
+
tokenRanges = []
|
|
2991
|
+
}) {
|
|
2992
|
+
if (isComposing) return null;
|
|
2993
|
+
let best = null;
|
|
2994
|
+
for (const trigger of triggers) {
|
|
2995
|
+
const candidate = findCandidate(text, caret, trigger);
|
|
2996
|
+
if (!candidate) continue;
|
|
2997
|
+
const match = validateCandidate(text, caret, trigger, candidate, dismissed, tokenRanges);
|
|
2998
|
+
if (!match) continue;
|
|
2999
|
+
if (!best || match.symbolStart > best.symbolStart || match.symbolStart === best.symbolStart && match.trigger.symbol.length > best.trigger.symbol.length) {
|
|
3000
|
+
best = match;
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
return best;
|
|
3004
|
+
}
|
|
3005
|
+
var LOADING_DELAY_MS = 120;
|
|
3006
|
+
var DISMISS_GRACE_MS = 120;
|
|
3007
|
+
var CIRCUIT_BREAKER_THRESHOLD = 2;
|
|
3008
|
+
var CLOSED_SUGGESTION_STATE = {
|
|
3009
|
+
isOpen: false,
|
|
3010
|
+
items: [],
|
|
3011
|
+
visibleItems: [],
|
|
3012
|
+
activeIndex: 0,
|
|
3013
|
+
loading: false,
|
|
3014
|
+
error: null,
|
|
3015
|
+
requestToken: 0
|
|
3016
|
+
};
|
|
3017
|
+
function createSuggestionController({ emit }) {
|
|
3018
|
+
let state = CLOSED_SUGGESTION_STATE;
|
|
3019
|
+
let match = null;
|
|
3020
|
+
let requestCounter = 0;
|
|
3021
|
+
let debounceTimer = null;
|
|
3022
|
+
let loadingTimer = null;
|
|
3023
|
+
let dismissTimer = null;
|
|
3024
|
+
const consecutiveFailures = /* @__PURE__ */ new Map();
|
|
3025
|
+
const tripped = /* @__PURE__ */ new Set();
|
|
3026
|
+
function clearTimer(timer) {
|
|
3027
|
+
if (timer !== null) clearTimeout(timer);
|
|
3028
|
+
return null;
|
|
3029
|
+
}
|
|
3030
|
+
function setState(patch) {
|
|
3031
|
+
state = { ...state, ...patch };
|
|
3032
|
+
}
|
|
3033
|
+
function sameOccurrence(a, b) {
|
|
3034
|
+
return a !== null && b !== null && a.trigger.id === b.trigger.id && a.symbolStart === b.symbolStart;
|
|
3035
|
+
}
|
|
3036
|
+
function closeInternal() {
|
|
3037
|
+
debounceTimer = clearTimer(debounceTimer);
|
|
3038
|
+
loadingTimer = clearTimer(loadingTimer);
|
|
3039
|
+
requestCounter++;
|
|
3040
|
+
match = null;
|
|
3041
|
+
state = CLOSED_SUGGESTION_STATE;
|
|
3042
|
+
}
|
|
3043
|
+
function applyResults(forMatch, items) {
|
|
3044
|
+
loadingTimer = clearTimer(loadingTimer);
|
|
3045
|
+
consecutiveFailures.set(forMatch.trigger.id, 0);
|
|
3046
|
+
setState({
|
|
3047
|
+
isOpen: true,
|
|
3048
|
+
items,
|
|
3049
|
+
visibleItems: items.slice(0, forMatch.trigger.maxVisibleResults),
|
|
3050
|
+
activeIndex: 0,
|
|
3051
|
+
loading: false,
|
|
3052
|
+
error: null
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
3055
|
+
function applyFailure(forMatch, error) {
|
|
3056
|
+
loadingTimer = clearTimer(loadingTimer);
|
|
3057
|
+
const triggerId = forMatch.trigger.id;
|
|
3058
|
+
const failures = (consecutiveFailures.get(triggerId) ?? 0) + 1;
|
|
3059
|
+
consecutiveFailures.set(triggerId, failures);
|
|
3060
|
+
if (failures >= CIRCUIT_BREAKER_THRESHOLD) {
|
|
3061
|
+
tripped.add(triggerId);
|
|
3062
|
+
closeInternal();
|
|
3063
|
+
return;
|
|
3064
|
+
}
|
|
3065
|
+
setState({
|
|
3066
|
+
isOpen: true,
|
|
3067
|
+
items: [],
|
|
3068
|
+
visibleItems: [],
|
|
3069
|
+
loading: false,
|
|
3070
|
+
error: error instanceof Error ? error.message : "Failed to load suggestions"
|
|
3071
|
+
});
|
|
3072
|
+
}
|
|
3073
|
+
function dispatch(forMatch, notifySync) {
|
|
3074
|
+
const token = ++requestCounter;
|
|
3075
|
+
setState({ requestToken: token });
|
|
3076
|
+
let result;
|
|
3077
|
+
try {
|
|
3078
|
+
result = forMatch.trigger.resolve(forMatch.query);
|
|
3079
|
+
} catch (error) {
|
|
3080
|
+
applyFailure(forMatch, error);
|
|
3081
|
+
if (notifySync) emit();
|
|
3082
|
+
return;
|
|
3083
|
+
}
|
|
3084
|
+
if (Array.isArray(result)) {
|
|
3085
|
+
applyResults(forMatch, result);
|
|
3086
|
+
if (notifySync) emit();
|
|
3087
|
+
return;
|
|
3088
|
+
}
|
|
3089
|
+
loadingTimer = clearTimer(loadingTimer);
|
|
3090
|
+
loadingTimer = setTimeout(() => {
|
|
3091
|
+
if (token !== requestCounter) return;
|
|
3092
|
+
setState({ isOpen: true, loading: true });
|
|
3093
|
+
emit();
|
|
3094
|
+
}, LOADING_DELAY_MS);
|
|
3095
|
+
result.then(
|
|
3096
|
+
(items) => {
|
|
3097
|
+
if (token !== requestCounter || !sameOccurrence(match, forMatch)) return;
|
|
3098
|
+
applyResults(forMatch, items);
|
|
3099
|
+
emit();
|
|
3100
|
+
},
|
|
3101
|
+
(error) => {
|
|
3102
|
+
if (token !== requestCounter || !sameOccurrence(match, forMatch)) return;
|
|
3103
|
+
applyFailure(forMatch, error);
|
|
3104
|
+
emit();
|
|
3105
|
+
}
|
|
3106
|
+
);
|
|
3107
|
+
}
|
|
3108
|
+
function schedule(forMatch) {
|
|
3109
|
+
debounceTimer = clearTimer(debounceTimer);
|
|
3110
|
+
if (forMatch.trigger.debounceMs <= 0) {
|
|
3111
|
+
dispatch(forMatch, false);
|
|
3112
|
+
return;
|
|
3113
|
+
}
|
|
3114
|
+
debounceTimer = setTimeout(() => {
|
|
3115
|
+
debounceTimer = null;
|
|
3116
|
+
if (sameOccurrence(match, forMatch) && match?.query === forMatch.query) {
|
|
3117
|
+
dispatch(forMatch, true);
|
|
3118
|
+
}
|
|
3119
|
+
}, forMatch.trigger.debounceMs);
|
|
3120
|
+
}
|
|
3121
|
+
return {
|
|
3122
|
+
get state() {
|
|
3123
|
+
return state;
|
|
3124
|
+
},
|
|
3125
|
+
sync(next) {
|
|
3126
|
+
if (next === null) {
|
|
3127
|
+
if (match !== null || state.isOpen) closeInternal();
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
3130
|
+
if (tripped.has(next.trigger.id)) {
|
|
3131
|
+
if (match !== null || state.isOpen) closeInternal();
|
|
3132
|
+
return;
|
|
3133
|
+
}
|
|
3134
|
+
const isSame = sameOccurrence(match, next);
|
|
3135
|
+
const queryChanged = !isSame || match?.query !== next.query;
|
|
3136
|
+
match = next;
|
|
3137
|
+
if (!isSame) {
|
|
3138
|
+
state = { ...CLOSED_SUGGESTION_STATE, isOpen: true, requestToken: state.requestToken };
|
|
3139
|
+
}
|
|
3140
|
+
if (queryChanged) schedule(next);
|
|
3141
|
+
},
|
|
3142
|
+
moveNext() {
|
|
3143
|
+
const count = state.items.length;
|
|
3144
|
+
if (!state.isOpen || count === 0) return;
|
|
3145
|
+
const wrap = match?.trigger.wrapNavigation ?? true;
|
|
3146
|
+
const next = wrap ? (state.activeIndex + 1) % count : Math.min(state.activeIndex + 1, count - 1);
|
|
3147
|
+
setState({ activeIndex: next });
|
|
3148
|
+
},
|
|
3149
|
+
movePrevious() {
|
|
3150
|
+
const count = state.items.length;
|
|
3151
|
+
if (!state.isOpen || count === 0) return;
|
|
3152
|
+
const wrap = match?.trigger.wrapNavigation ?? true;
|
|
3153
|
+
const previous = wrap ? (state.activeIndex - 1 + count) % count : Math.max(state.activeIndex - 1, 0);
|
|
3154
|
+
setState({ activeIndex: previous });
|
|
3155
|
+
},
|
|
3156
|
+
setActiveIndex(index) {
|
|
3157
|
+
if (!state.isOpen || state.items.length === 0) return;
|
|
3158
|
+
setState({ activeIndex: Math.max(0, Math.min(index, state.items.length - 1)) });
|
|
3159
|
+
},
|
|
3160
|
+
retry() {
|
|
3161
|
+
if (match === null) return;
|
|
3162
|
+
if (tripped.has(match.trigger.id)) return;
|
|
3163
|
+
setState({ error: null });
|
|
3164
|
+
dispatch(match, false);
|
|
3165
|
+
},
|
|
3166
|
+
dismissDeferred(onClosed) {
|
|
3167
|
+
dismissTimer = clearTimer(dismissTimer);
|
|
3168
|
+
dismissTimer = setTimeout(() => {
|
|
3169
|
+
dismissTimer = null;
|
|
3170
|
+
closeInternal();
|
|
3171
|
+
onClosed();
|
|
3172
|
+
}, DISMISS_GRACE_MS);
|
|
3173
|
+
},
|
|
3174
|
+
cancelDeferredDismiss() {
|
|
3175
|
+
dismissTimer = clearTimer(dismissTimer);
|
|
3176
|
+
},
|
|
3177
|
+
close() {
|
|
3178
|
+
dismissTimer = clearTimer(dismissTimer);
|
|
3179
|
+
closeInternal();
|
|
3180
|
+
},
|
|
3181
|
+
isTripped(triggerId) {
|
|
3182
|
+
return tripped.has(triggerId);
|
|
3183
|
+
},
|
|
3184
|
+
destroy() {
|
|
3185
|
+
debounceTimer = clearTimer(debounceTimer);
|
|
3186
|
+
loadingTimer = clearTimer(loadingTimer);
|
|
3187
|
+
dismissTimer = clearTimer(dismissTimer);
|
|
3188
|
+
match = null;
|
|
3189
|
+
state = CLOSED_SUGGESTION_STATE;
|
|
3190
|
+
}
|
|
3191
|
+
};
|
|
3192
|
+
}
|
|
3193
|
+
function diffEdit(oldText, newText) {
|
|
3194
|
+
if (oldText === newText) return null;
|
|
3195
|
+
const minLen = Math.min(oldText.length, newText.length);
|
|
3196
|
+
let prefix = 0;
|
|
3197
|
+
while (prefix < minLen && oldText[prefix] === newText[prefix]) prefix++;
|
|
3198
|
+
let suffix = 0;
|
|
3199
|
+
while (suffix < minLen - prefix && oldText[oldText.length - 1 - suffix] === newText[newText.length - 1 - suffix]) {
|
|
3200
|
+
suffix++;
|
|
3201
|
+
}
|
|
3202
|
+
return { start: prefix, oldEnd: oldText.length - suffix, newEnd: newText.length - suffix };
|
|
3203
|
+
}
|
|
3204
|
+
function nearestBoundary(offset, token) {
|
|
3205
|
+
return offset - token.start <= token.end - offset ? token.start : token.end;
|
|
3206
|
+
}
|
|
3207
|
+
function applyValueEdit({
|
|
3208
|
+
oldValue,
|
|
3209
|
+
newValue,
|
|
3210
|
+
tokens,
|
|
3211
|
+
newSelection,
|
|
3212
|
+
maxLength
|
|
3213
|
+
}) {
|
|
3214
|
+
const noChange = {
|
|
3215
|
+
value: oldValue,
|
|
3216
|
+
tokens: [...tokens],
|
|
3217
|
+
selection: newSelection,
|
|
3218
|
+
rejected: false,
|
|
3219
|
+
trimmed: false,
|
|
3220
|
+
removedTokens: [],
|
|
3221
|
+
edit: null
|
|
3222
|
+
};
|
|
3223
|
+
const diff = diffEdit(oldValue, newValue);
|
|
3224
|
+
if (!diff) return noChange;
|
|
3225
|
+
const insertedRaw = newValue.slice(diff.start, diff.newEnd);
|
|
3226
|
+
if (diff.oldEnd === diff.start) {
|
|
3227
|
+
const host = tokens.find((t) => t.start < diff.start && diff.start < t.end);
|
|
3228
|
+
if (host) {
|
|
3229
|
+
const caret2 = nearestBoundary(diff.start, host);
|
|
3230
|
+
return { ...noChange, rejected: true, selection: { start: caret2, end: caret2 } };
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
let expStart = diff.start;
|
|
3234
|
+
let expOldEnd = diff.oldEnd;
|
|
3235
|
+
const removedTokens = [];
|
|
3236
|
+
for (const token of tokens) {
|
|
3237
|
+
const overlaps = token.start < expOldEnd && token.end > expStart;
|
|
3238
|
+
if (!overlaps) continue;
|
|
3239
|
+
removedTokens.push(token);
|
|
3240
|
+
expStart = Math.min(expStart, token.start);
|
|
3241
|
+
expOldEnd = Math.max(expOldEnd, token.end);
|
|
3242
|
+
}
|
|
3243
|
+
let inserted = insertedRaw;
|
|
3244
|
+
let trimmed = false;
|
|
3245
|
+
if (maxLength !== void 0 && inserted.length > 0) {
|
|
3246
|
+
const baseLength = graphemeLength(oldValue.slice(0, expStart)) + graphemeLength(oldValue.slice(expOldEnd));
|
|
3247
|
+
const budget = Math.max(0, maxLength - baseLength);
|
|
3248
|
+
if (graphemeLength(inserted) > budget) {
|
|
3249
|
+
inserted = clampGraphemes(inserted, budget);
|
|
3250
|
+
trimmed = true;
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
const value = oldValue.slice(0, expStart) + inserted + oldValue.slice(expOldEnd);
|
|
3254
|
+
const delta = expStart + inserted.length - expOldEnd;
|
|
3255
|
+
const nextTokens = tokens.filter((t) => !removedTokens.includes(t)).map((t) => t.start >= expOldEnd ? { ...t, start: t.start + delta, end: t.end + delta } : t);
|
|
3256
|
+
const appliedMatchesRaw = expStart === diff.start && expOldEnd === diff.oldEnd && !trimmed;
|
|
3257
|
+
const caret = expStart + inserted.length;
|
|
3258
|
+
const selection = appliedMatchesRaw ? newSelection : { start: caret, end: caret };
|
|
3259
|
+
return {
|
|
3260
|
+
value,
|
|
3261
|
+
tokens: nextTokens,
|
|
3262
|
+
selection: clampSelectionToValue(selection, value),
|
|
3263
|
+
rejected: false,
|
|
3264
|
+
trimmed,
|
|
3265
|
+
removedTokens,
|
|
3266
|
+
edit: { start: expStart, oldEnd: expOldEnd, newEnd: expStart + inserted.length }
|
|
3267
|
+
};
|
|
3268
|
+
}
|
|
3269
|
+
function clampSelectionToValue(selection, value) {
|
|
3270
|
+
const clamp3 = (n) => Math.max(0, Math.min(n, value.length));
|
|
3271
|
+
return { start: clamp3(selection.start), end: clamp3(selection.end) };
|
|
3272
|
+
}
|
|
3273
|
+
function snapSelectionToTokens(tokens, selection, previous) {
|
|
3274
|
+
const inside = (offset) => tokens.find((t) => t.start < offset && offset < t.end);
|
|
3275
|
+
if (selection.start === selection.end) {
|
|
3276
|
+
const host = inside(selection.start);
|
|
3277
|
+
if (!host) return selection;
|
|
3278
|
+
let caret;
|
|
3279
|
+
if (previous && previous.start === previous.end && previous.start !== selection.start) {
|
|
3280
|
+
caret = selection.start > previous.start ? host.end : host.start;
|
|
3281
|
+
} else {
|
|
3282
|
+
caret = nearestBoundary(selection.start, host);
|
|
3283
|
+
}
|
|
3284
|
+
return { start: caret, end: caret };
|
|
3285
|
+
}
|
|
3286
|
+
const startHost = inside(selection.start);
|
|
3287
|
+
const endHost = inside(selection.end);
|
|
3288
|
+
return {
|
|
3289
|
+
start: startHost ? startHost.start : selection.start,
|
|
3290
|
+
end: endHost ? endHost.end : selection.end
|
|
3291
|
+
};
|
|
3292
|
+
}
|
|
3293
|
+
function expandRangeOverTokens(tokens, range) {
|
|
3294
|
+
let { start, end } = range;
|
|
3295
|
+
for (const token of tokens) {
|
|
3296
|
+
if (token.start < end && token.end > start) {
|
|
3297
|
+
start = Math.min(start, token.start);
|
|
3298
|
+
end = Math.max(end, token.end);
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
return { start, end };
|
|
3302
|
+
}
|
|
3303
|
+
function commitTokenAt({ value, tokens, start, end, token }) {
|
|
3304
|
+
const display = token.display;
|
|
3305
|
+
const nextValue = value.slice(0, start) + display + value.slice(end);
|
|
3306
|
+
const delta = display.length - (end - start);
|
|
3307
|
+
const placed = { ...token, start, end: start + display.length };
|
|
3308
|
+
const shifted = tokens.map(
|
|
3309
|
+
(t) => t.start >= end ? { ...t, start: t.start + delta, end: t.end + delta } : t
|
|
3310
|
+
);
|
|
3311
|
+
const nextTokens = [...shifted, placed].sort((a, b) => a.start - b.start);
|
|
3312
|
+
const caret = placed.end;
|
|
3313
|
+
return { value: nextValue, tokens: nextTokens, selection: { start: caret, end: caret } };
|
|
3314
|
+
}
|
|
3315
|
+
function serializeTokens(value, tokens) {
|
|
3316
|
+
const resolved = tokens.map((t) => ({
|
|
3317
|
+
type: t.triggerId,
|
|
3318
|
+
id: t.id,
|
|
3319
|
+
display: t.display,
|
|
3320
|
+
start: t.start,
|
|
3321
|
+
end: t.end
|
|
3322
|
+
}));
|
|
3323
|
+
return { plainText: value, tokens: resolved };
|
|
3324
|
+
}
|
|
3325
|
+
function detectTypedEmoji(value, caret) {
|
|
3326
|
+
const hit = detectEmojiShortcode(value.slice(0, caret));
|
|
3327
|
+
if (!hit) return null;
|
|
3328
|
+
return { shortcode: hit.shortcode, unicode: hit.unicode, start: caret - hit.shortcode.length };
|
|
3329
|
+
}
|
|
3330
|
+
var DEFAULT_DRAFT_DEBOUNCE_MS = 400;
|
|
3331
|
+
var DEFAULT_TYPING_SIGNAL_INTERVAL_MS = 3e3;
|
|
3332
|
+
function validateDraft(raw) {
|
|
3333
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
3334
|
+
const draft = raw;
|
|
3335
|
+
if (typeof draft.value !== "string") return null;
|
|
3336
|
+
if (!Array.isArray(draft.tokens)) return null;
|
|
3337
|
+
if (!Array.isArray(draft.attachmentIds)) return null;
|
|
3338
|
+
for (const token of draft.tokens) {
|
|
3339
|
+
if (typeof token !== "object" || token === null || typeof token.start !== "number" || typeof token.end !== "number" || typeof token.display !== "string" || // The one invariant that matters: ranges must project the display.
|
|
3340
|
+
draft.value.substring(token.start, token.end) !== token.display) {
|
|
3341
|
+
return null;
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
return {
|
|
3345
|
+
value: draft.value,
|
|
3346
|
+
tokens: draft.tokens,
|
|
3347
|
+
attachmentIds: draft.attachmentIds,
|
|
3348
|
+
updatedAt: typeof draft.updatedAt === "number" ? draft.updatedAt : 0
|
|
3349
|
+
};
|
|
3350
|
+
}
|
|
3351
|
+
function createComposer(config = {}) {
|
|
3352
|
+
const now = config.now ?? (() => Date.now());
|
|
3353
|
+
const generateId$1 = config.generateId ?? generateId;
|
|
3354
|
+
const onEvent = config.onEvent ?? (() => void 0);
|
|
3355
|
+
const triggers = (config.triggers ?? []).map(resolveTriggerConfig);
|
|
3356
|
+
const draftDebounceMs = config.draftDebounceMs ?? DEFAULT_DRAFT_DEBOUNCE_MS;
|
|
3357
|
+
const typingSignalIntervalMs = config.typingSignalIntervalMs ?? DEFAULT_TYPING_SIGNAL_INTERVAL_MS;
|
|
3358
|
+
const emojiTrigger = triggers.find((t) => t.symbol === ":") ?? null;
|
|
3359
|
+
let value = config.initialValue ?? "";
|
|
3360
|
+
let tokens = [...config.initialTokens ?? []];
|
|
3361
|
+
let selection = { start: value.length, end: value.length };
|
|
3362
|
+
let isComposing = false;
|
|
3363
|
+
let isBusy = false;
|
|
3364
|
+
let disabled = false;
|
|
3365
|
+
let readOnly = false;
|
|
3366
|
+
let error = null;
|
|
3367
|
+
let attachments = [];
|
|
3368
|
+
let mode = "compose";
|
|
3369
|
+
let editingMessageId;
|
|
3370
|
+
let preEditSnapshot = null;
|
|
3371
|
+
let activeMatch = null;
|
|
3372
|
+
let dismissed = [];
|
|
3373
|
+
let clipShadow = null;
|
|
3374
|
+
let lastTypingAt = Number.NEGATIVE_INFINITY;
|
|
3375
|
+
let draftTimer = null;
|
|
3376
|
+
let destroyed = false;
|
|
3377
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
3378
|
+
if (config.draftStore && config.draftKey) {
|
|
3379
|
+
try {
|
|
3380
|
+
const draft = validateDraft(config.draftStore.read(config.draftKey));
|
|
3381
|
+
if (draft) {
|
|
3382
|
+
value = draft.value;
|
|
3383
|
+
tokens = draft.tokens;
|
|
3384
|
+
selection = { start: value.length, end: value.length };
|
|
3385
|
+
}
|
|
3386
|
+
} catch {
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
const suggestions = createSuggestionController({ emit: () => emit() });
|
|
3390
|
+
function toActiveTriggerState(match) {
|
|
3391
|
+
if (!match) return null;
|
|
3392
|
+
return {
|
|
3393
|
+
triggerId: match.trigger.id,
|
|
3394
|
+
symbol: match.trigger.symbol,
|
|
3395
|
+
symbolStart: match.symbolStart,
|
|
3396
|
+
caret: match.caret,
|
|
3397
|
+
query: match.query
|
|
3398
|
+
};
|
|
3399
|
+
}
|
|
3400
|
+
function buildState() {
|
|
3401
|
+
const counter = computeCounter(value, config.maxLength);
|
|
3402
|
+
const overBudget = counter.remaining !== null && counter.remaining < 0;
|
|
3403
|
+
return {
|
|
3404
|
+
value,
|
|
3405
|
+
selection,
|
|
3406
|
+
isComposing,
|
|
3407
|
+
isBusy,
|
|
3408
|
+
disabled,
|
|
3409
|
+
readOnly,
|
|
3410
|
+
isEmpty: payloadFor(value).length === 0 && attachments.length === 0,
|
|
3411
|
+
canSend: canSend({ text: value, attachments, disabled, readOnly, busy: isBusy }) && !overBudget,
|
|
3412
|
+
error,
|
|
3413
|
+
attachments: [...attachments],
|
|
3414
|
+
tokens: [...tokens],
|
|
3415
|
+
activeTrigger: toActiveTriggerState(activeMatch),
|
|
3416
|
+
suggestion: destroyed ? CLOSED_SUGGESTION_STATE : suggestions.state,
|
|
3417
|
+
counter,
|
|
3418
|
+
mode,
|
|
3419
|
+
editingMessageId
|
|
3420
|
+
};
|
|
3421
|
+
}
|
|
3422
|
+
function emit() {
|
|
3423
|
+
if (destroyed) return;
|
|
3424
|
+
const snapshot = buildState();
|
|
3425
|
+
for (const listener of listeners) listener(snapshot);
|
|
3426
|
+
}
|
|
3427
|
+
function shiftDismissedForEdit(editStart, editOldEnd, delta) {
|
|
3428
|
+
dismissed = dismissed.map((d) => d.symbolStart >= editOldEnd ? { ...d, symbolStart: d.symbolStart + delta } : d).filter((d) => {
|
|
3429
|
+
if (d.symbolStart >= editStart && d.symbolStart < editOldEnd) return false;
|
|
3430
|
+
const trigger = triggers.find((t) => t.id === d.triggerId);
|
|
3431
|
+
return trigger !== void 0 && value.startsWith(trigger.symbol, d.symbolStart);
|
|
3432
|
+
});
|
|
3433
|
+
}
|
|
3434
|
+
function recomputeTriggers() {
|
|
3435
|
+
const collapsed = selection.start === selection.end;
|
|
3436
|
+
activeMatch = collapsed && !isComposing && !disabled && !readOnly ? detectActiveTrigger({
|
|
3437
|
+
text: value,
|
|
3438
|
+
caret: selection.start,
|
|
3439
|
+
triggers,
|
|
3440
|
+
isComposing,
|
|
3441
|
+
dismissed,
|
|
3442
|
+
tokenRanges: tokens
|
|
3443
|
+
}) : null;
|
|
3444
|
+
suggestions.sync(activeMatch);
|
|
3445
|
+
}
|
|
3446
|
+
function fireTypingSignal() {
|
|
3447
|
+
const at = now();
|
|
3448
|
+
if (at - lastTypingAt >= typingSignalIntervalMs) {
|
|
3449
|
+
lastTypingAt = at;
|
|
3450
|
+
onEvent({ type: "typing" });
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
function scheduleDraftWrite() {
|
|
3454
|
+
if (!config.draftStore || !config.draftKey) return;
|
|
3455
|
+
if (draftTimer !== null) clearTimeout(draftTimer);
|
|
3456
|
+
draftTimer = setTimeout(() => {
|
|
3457
|
+
draftTimer = null;
|
|
3458
|
+
if (isComposing || destroyed) return;
|
|
3459
|
+
config.draftStore?.write(config.draftKey, {
|
|
3460
|
+
value,
|
|
3461
|
+
tokens: [...tokens],
|
|
3462
|
+
attachmentIds: attachments.map((a) => a.id),
|
|
3463
|
+
updatedAt: now()
|
|
3464
|
+
});
|
|
3465
|
+
}, draftDebounceMs);
|
|
3466
|
+
}
|
|
3467
|
+
function cancelDraftWrite() {
|
|
3468
|
+
if (draftTimer !== null) {
|
|
3469
|
+
clearTimeout(draftTimer);
|
|
3470
|
+
draftTimer = null;
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
function clearPersistedDraft() {
|
|
3474
|
+
cancelDraftWrite();
|
|
3475
|
+
if (config.draftStore && config.draftKey) config.draftStore.clear(config.draftKey);
|
|
3476
|
+
}
|
|
3477
|
+
function maybeCommitTypedEmoji() {
|
|
3478
|
+
if (!emojiTrigger || selection.start !== selection.end) return;
|
|
3479
|
+
const caretBefore = selection.start;
|
|
3480
|
+
const hit = detectTypedEmoji(value, caretBefore);
|
|
3481
|
+
if (!hit) return;
|
|
3482
|
+
if (tokens.some((t) => t.start < caretBefore && hit.start < t.end)) return;
|
|
3483
|
+
const token = {
|
|
3484
|
+
triggerId: emojiTrigger.id,
|
|
3485
|
+
symbol: emojiTrigger.symbol,
|
|
3486
|
+
id: hit.shortcode,
|
|
3487
|
+
label: hit.shortcode.slice(1, -1),
|
|
3488
|
+
display: hit.unicode
|
|
3489
|
+
};
|
|
3490
|
+
const committed = commitTokenAt({
|
|
3491
|
+
value,
|
|
3492
|
+
tokens,
|
|
3493
|
+
start: hit.start,
|
|
3494
|
+
end: caretBefore,
|
|
3495
|
+
token
|
|
3496
|
+
});
|
|
3497
|
+
const delta = committed.value.length - value.length;
|
|
3498
|
+
value = committed.value;
|
|
3499
|
+
tokens = committed.tokens;
|
|
3500
|
+
selection = committed.selection;
|
|
3501
|
+
shiftDismissedForEdit(hit.start, caretBefore, delta);
|
|
3502
|
+
}
|
|
3503
|
+
function mutateValue(newText, newSelection, opts = {}) {
|
|
3504
|
+
const previousSelection = selection;
|
|
3505
|
+
if (isComposing) {
|
|
3506
|
+
const result2 = applyValueEdit({ oldValue: value, newValue: newText, tokens, newSelection });
|
|
3507
|
+
value = result2.value;
|
|
3508
|
+
tokens = result2.tokens;
|
|
3509
|
+
selection = result2.selection;
|
|
3510
|
+
emit();
|
|
3511
|
+
return { applied: true, editStart: result2.edit?.start ?? newSelection.start };
|
|
3512
|
+
}
|
|
3513
|
+
const result = applyValueEdit({
|
|
3514
|
+
oldValue: value,
|
|
3515
|
+
newValue: newText,
|
|
3516
|
+
tokens,
|
|
3517
|
+
newSelection,
|
|
3518
|
+
maxLength: config.maxLength
|
|
3519
|
+
});
|
|
3520
|
+
if (result.rejected) {
|
|
3521
|
+
onEvent({ type: "edit-rejected", reason: "inside-token" });
|
|
3522
|
+
selection = result.selection;
|
|
3523
|
+
recomputeTriggers();
|
|
3524
|
+
emit();
|
|
3525
|
+
return { applied: false, editStart: 0 };
|
|
3526
|
+
}
|
|
3527
|
+
if (result.trimmed && opts.trimEventOnClamp !== false) {
|
|
3528
|
+
onEvent({ type: "paste-trimmed" });
|
|
3529
|
+
}
|
|
3530
|
+
const editStart = result.edit?.start ?? newSelection.start;
|
|
3531
|
+
value = result.value;
|
|
3532
|
+
tokens = result.tokens;
|
|
3533
|
+
selection = snapSelectionToTokens(tokens, result.selection, previousSelection);
|
|
3534
|
+
if (result.edit) {
|
|
3535
|
+
shiftDismissedForEdit(
|
|
3536
|
+
result.edit.start,
|
|
3537
|
+
result.edit.oldEnd,
|
|
3538
|
+
result.edit.newEnd - result.edit.oldEnd
|
|
3539
|
+
);
|
|
3540
|
+
}
|
|
3541
|
+
maybeCommitTypedEmoji();
|
|
3542
|
+
recomputeTriggers();
|
|
3543
|
+
if (!opts.programmatic) fireTypingSignal();
|
|
3544
|
+
scheduleDraftWrite();
|
|
3545
|
+
emit();
|
|
3546
|
+
return { applied: true, editStart };
|
|
3547
|
+
}
|
|
3548
|
+
function buildSubmissionTokens() {
|
|
3549
|
+
const plainText = payloadFor(value);
|
|
3550
|
+
const leading = value.length - value.trimStart().length;
|
|
3551
|
+
const serialized = serializeTokens(value, tokens);
|
|
3552
|
+
return {
|
|
3553
|
+
plainText,
|
|
3554
|
+
tokens: serialized.tokens.map((t) => ({ ...t, start: t.start - leading, end: t.end - leading }))
|
|
3555
|
+
};
|
|
3556
|
+
}
|
|
3557
|
+
function commitSuggestion(index) {
|
|
3558
|
+
const match = activeMatch;
|
|
3559
|
+
const menu = suggestions.state;
|
|
3560
|
+
if (!match || !menu.isOpen) return false;
|
|
3561
|
+
const item = menu.items[index ?? menu.activeIndex];
|
|
3562
|
+
if (!item) return false;
|
|
3563
|
+
const display = match.trigger.toDisplay(item);
|
|
3564
|
+
if (config.maxLength !== void 0) {
|
|
3565
|
+
const replacedSpan = value.slice(match.symbolStart, match.caret);
|
|
3566
|
+
const nextLength = graphemeLength(value) - graphemeLength(replacedSpan) + graphemeLength(display);
|
|
3567
|
+
if (nextLength > config.maxLength) {
|
|
3568
|
+
onEvent({ type: "insert-rejected", reason: "max-length" });
|
|
3569
|
+
emit();
|
|
3570
|
+
return false;
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
const token = {
|
|
3574
|
+
triggerId: match.trigger.id,
|
|
3575
|
+
symbol: match.trigger.symbol,
|
|
3576
|
+
id: item.id,
|
|
3577
|
+
label: item.display,
|
|
3578
|
+
display,
|
|
3579
|
+
metadata: item.metadata
|
|
3580
|
+
};
|
|
3581
|
+
const committed = commitTokenAt({
|
|
3582
|
+
value,
|
|
3583
|
+
tokens,
|
|
3584
|
+
start: match.symbolStart,
|
|
3585
|
+
end: match.caret,
|
|
3586
|
+
token
|
|
3587
|
+
});
|
|
3588
|
+
const delta = committed.value.length - value.length;
|
|
3589
|
+
value = committed.value;
|
|
3590
|
+
tokens = committed.tokens;
|
|
3591
|
+
selection = committed.selection;
|
|
3592
|
+
shiftDismissedForEdit(match.symbolStart, match.caret, delta);
|
|
3593
|
+
suggestions.cancelDeferredDismiss();
|
|
3594
|
+
activeMatch = null;
|
|
3595
|
+
suggestions.sync(null);
|
|
3596
|
+
scheduleDraftWrite();
|
|
3597
|
+
emit();
|
|
3598
|
+
return true;
|
|
3599
|
+
}
|
|
3600
|
+
function performSubmit() {
|
|
3601
|
+
const counter = computeCounter(value, config.maxLength);
|
|
3602
|
+
const overBudget = counter.remaining !== null && counter.remaining < 0;
|
|
3603
|
+
if (!canSend({ text: value, attachments, disabled, readOnly, busy: isBusy }) || overBudget) {
|
|
3604
|
+
return null;
|
|
3605
|
+
}
|
|
3606
|
+
const { plainText, tokens: submissionTokens } = buildSubmissionTokens();
|
|
3607
|
+
if (config.validator) {
|
|
3608
|
+
const verdict = config.validator(plainText, submissionTokens);
|
|
3609
|
+
if (!verdict.isValid) {
|
|
3610
|
+
error = verdict.reason ?? "Message failed validation";
|
|
3611
|
+
emit();
|
|
3612
|
+
return null;
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
const submission = {
|
|
3616
|
+
plainText,
|
|
3617
|
+
tokens: submissionTokens,
|
|
3618
|
+
attachments: [...attachments],
|
|
3619
|
+
replyToMessageId: config.replyToMessageId,
|
|
3620
|
+
...mode === "edit" ? { editingMessageId } : {}
|
|
3621
|
+
};
|
|
3622
|
+
value = "";
|
|
3623
|
+
tokens = [];
|
|
3624
|
+
attachments = [];
|
|
3625
|
+
selection = { start: 0, end: 0 };
|
|
3626
|
+
error = null;
|
|
3627
|
+
activeMatch = null;
|
|
3628
|
+
dismissed = [];
|
|
3629
|
+
clipShadow = null;
|
|
3630
|
+
mode = "compose";
|
|
3631
|
+
editingMessageId = void 0;
|
|
3632
|
+
preEditSnapshot = null;
|
|
3633
|
+
suggestions.close();
|
|
3634
|
+
clearPersistedDraft();
|
|
3635
|
+
emit();
|
|
3636
|
+
return submission;
|
|
3637
|
+
}
|
|
3638
|
+
const api = {
|
|
3639
|
+
getState() {
|
|
3640
|
+
return buildState();
|
|
3641
|
+
},
|
|
3642
|
+
subscribe(listener) {
|
|
3643
|
+
listeners.add(listener);
|
|
3644
|
+
return () => listeners.delete(listener);
|
|
3645
|
+
},
|
|
3646
|
+
setValue(text, sel, opts) {
|
|
3647
|
+
if (destroyed || disabled) return;
|
|
3648
|
+
if (readOnly) {
|
|
3649
|
+
if (text === value && sel) api.setSelection(sel);
|
|
3650
|
+
return;
|
|
3651
|
+
}
|
|
3652
|
+
const nextSelection = sel ?? { start: text.length, end: text.length };
|
|
3653
|
+
mutateValue(text, nextSelection, { programmatic: opts?.programmatic });
|
|
3654
|
+
},
|
|
3655
|
+
setSelection(sel) {
|
|
3656
|
+
if (destroyed || disabled) return;
|
|
3657
|
+
const previous = selection;
|
|
3658
|
+
selection = snapSelectionToTokens(tokens, {
|
|
3659
|
+
start: Math.max(0, Math.min(sel.start, value.length)),
|
|
3660
|
+
end: Math.max(0, Math.min(sel.end, value.length))
|
|
3661
|
+
}, previous);
|
|
3662
|
+
recomputeTriggers();
|
|
3663
|
+
emit();
|
|
3664
|
+
},
|
|
3665
|
+
insertTextAtCursor(text) {
|
|
3666
|
+
if (destroyed) return;
|
|
3667
|
+
if (disabled) {
|
|
3668
|
+
onEvent({ type: "insert-rejected", reason: "disabled" });
|
|
3669
|
+
return;
|
|
3670
|
+
}
|
|
3671
|
+
if (readOnly) {
|
|
3672
|
+
onEvent({ type: "insert-rejected", reason: "read-only" });
|
|
3673
|
+
return;
|
|
3674
|
+
}
|
|
3675
|
+
if (isComposing) {
|
|
3676
|
+
onEvent({ type: "insert-rejected", reason: "composing" });
|
|
3677
|
+
return;
|
|
3678
|
+
}
|
|
3679
|
+
if (config.maxLength !== void 0) {
|
|
3680
|
+
const range = expandRangeOverTokens(tokens, selection);
|
|
3681
|
+
const base = graphemeLength(value.slice(0, range.start)) + graphemeLength(value.slice(range.end));
|
|
3682
|
+
if (base + graphemeLength(text) > config.maxLength) {
|
|
3683
|
+
onEvent({ type: "insert-rejected", reason: "max-length" });
|
|
3684
|
+
return;
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
const nextText = value.slice(0, selection.start) + text + value.slice(selection.end);
|
|
3688
|
+
const caret = selection.start + text.length;
|
|
3689
|
+
mutateValue(nextText, { start: caret, end: caret });
|
|
3690
|
+
},
|
|
3691
|
+
setComposing(composing) {
|
|
3692
|
+
if (destroyed || isComposing === composing) return;
|
|
3693
|
+
isComposing = composing;
|
|
3694
|
+
if (!composing) {
|
|
3695
|
+
if (config.maxLength !== void 0 && graphemeLength(value) > config.maxLength) {
|
|
3696
|
+
value = clampGraphemes(value, config.maxLength);
|
|
3697
|
+
tokens = tokens.filter((t) => t.end <= value.length);
|
|
3698
|
+
selection = {
|
|
3699
|
+
start: Math.min(selection.start, value.length),
|
|
3700
|
+
end: Math.min(selection.end, value.length)
|
|
3701
|
+
};
|
|
3702
|
+
}
|
|
3703
|
+
maybeCommitTypedEmoji();
|
|
3704
|
+
recomputeTriggers();
|
|
3705
|
+
scheduleDraftWrite();
|
|
3706
|
+
} else {
|
|
3707
|
+
activeMatch = null;
|
|
3708
|
+
suggestions.sync(null);
|
|
3709
|
+
}
|
|
3710
|
+
emit();
|
|
3711
|
+
},
|
|
3712
|
+
applyEnter({ shiftPressed }) {
|
|
3713
|
+
if (destroyed || disabled || readOnly) return "noop";
|
|
3714
|
+
const menu = suggestions.state;
|
|
3715
|
+
if (menu.isOpen && !isComposing) {
|
|
3716
|
+
if (menu.items.length > 0) {
|
|
3717
|
+
return commitSuggestion() ? "committed-suggestion" : "noop";
|
|
3718
|
+
}
|
|
3719
|
+
return "noop";
|
|
3720
|
+
}
|
|
3721
|
+
if (!shouldSubmitOnEnter({ shiftPressed, isComposing })) {
|
|
3722
|
+
return isComposing ? "noop" : "newline";
|
|
3723
|
+
}
|
|
3724
|
+
return performSubmit() ? "submitted" : "noop";
|
|
3725
|
+
},
|
|
3726
|
+
moveSuggestionNext() {
|
|
3727
|
+
suggestions.moveNext();
|
|
3728
|
+
emit();
|
|
3729
|
+
},
|
|
3730
|
+
moveSuggestionPrevious() {
|
|
3731
|
+
suggestions.movePrevious();
|
|
3732
|
+
emit();
|
|
3733
|
+
},
|
|
3734
|
+
setSuggestionActiveIndex(index) {
|
|
3735
|
+
suggestions.setActiveIndex(index);
|
|
3736
|
+
emit();
|
|
3737
|
+
},
|
|
3738
|
+
applySuggestion(index) {
|
|
3739
|
+
commitSuggestion(index);
|
|
3740
|
+
},
|
|
3741
|
+
dismissSuggestion() {
|
|
3742
|
+
if (activeMatch) {
|
|
3743
|
+
dismissed.push({ triggerId: activeMatch.trigger.id, symbolStart: activeMatch.symbolStart });
|
|
3744
|
+
activeMatch = null;
|
|
3745
|
+
}
|
|
3746
|
+
suggestions.close();
|
|
3747
|
+
emit();
|
|
3748
|
+
},
|
|
3749
|
+
dismissSuggestionDeferred() {
|
|
3750
|
+
suggestions.dismissDeferred(() => {
|
|
3751
|
+
activeMatch = null;
|
|
3752
|
+
emit();
|
|
3753
|
+
});
|
|
3754
|
+
},
|
|
3755
|
+
retrySuggestions() {
|
|
3756
|
+
suggestions.retry();
|
|
3757
|
+
emit();
|
|
3758
|
+
},
|
|
3759
|
+
addAttachment(draft) {
|
|
3760
|
+
if (destroyed) return null;
|
|
3761
|
+
if (config.maxAttachments !== void 0 && attachments.length >= config.maxAttachments) {
|
|
3762
|
+
onEvent({ type: "attachment-rejected", reason: "max-attachments", name: draft.name });
|
|
3763
|
+
return null;
|
|
3764
|
+
}
|
|
3765
|
+
if (config.maxAttachmentSizeBytes !== void 0 && draft.sizeBytes !== void 0 && draft.sizeBytes > config.maxAttachmentSizeBytes) {
|
|
3766
|
+
onEvent({ type: "attachment-rejected", reason: "max-size", name: draft.name });
|
|
3767
|
+
return null;
|
|
3768
|
+
}
|
|
3769
|
+
if (config.acceptAttachment) {
|
|
3770
|
+
const verdict = config.acceptAttachment(draft);
|
|
3771
|
+
if (verdict !== true) {
|
|
3772
|
+
onEvent({
|
|
3773
|
+
type: "attachment-rejected",
|
|
3774
|
+
reason: "not-accepted",
|
|
3775
|
+
name: draft.name,
|
|
3776
|
+
...typeof verdict === "string" ? { detail: verdict } : {}
|
|
3777
|
+
});
|
|
3778
|
+
return null;
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
const id = draft.id ?? generateId$1("rfr-attachment");
|
|
3782
|
+
attachments = [...attachments, { ...draft, id, status: draft.status ?? "pending" }];
|
|
3783
|
+
scheduleDraftWrite();
|
|
3784
|
+
emit();
|
|
3785
|
+
return id;
|
|
3786
|
+
},
|
|
3787
|
+
updateAttachment(id, patch) {
|
|
3788
|
+
if (destroyed) return;
|
|
3789
|
+
attachments = attachments.map((a) => a.id === id ? { ...a, ...patch, id } : a);
|
|
3790
|
+
emit();
|
|
3791
|
+
},
|
|
3792
|
+
removeAttachment(id) {
|
|
3793
|
+
if (destroyed) return;
|
|
3794
|
+
attachments = attachments.filter((a) => a.id !== id);
|
|
3795
|
+
scheduleDraftWrite();
|
|
3796
|
+
emit();
|
|
3797
|
+
},
|
|
3798
|
+
setBusy(busy) {
|
|
3799
|
+
if (destroyed || isBusy === busy) return;
|
|
3800
|
+
isBusy = busy;
|
|
3801
|
+
emit();
|
|
3802
|
+
},
|
|
3803
|
+
setError(nextError) {
|
|
3804
|
+
if (destroyed) return;
|
|
3805
|
+
error = nextError;
|
|
3806
|
+
emit();
|
|
3807
|
+
},
|
|
3808
|
+
setDisabled(nextDisabled) {
|
|
3809
|
+
if (destroyed || disabled === nextDisabled) return;
|
|
3810
|
+
disabled = nextDisabled;
|
|
3811
|
+
if (disabled) {
|
|
3812
|
+
activeMatch = null;
|
|
3813
|
+
suggestions.close();
|
|
3814
|
+
}
|
|
3815
|
+
emit();
|
|
3816
|
+
},
|
|
3817
|
+
setReadOnly(nextReadOnly) {
|
|
3818
|
+
if (destroyed || readOnly === nextReadOnly) return;
|
|
3819
|
+
readOnly = nextReadOnly;
|
|
3820
|
+
if (readOnly) {
|
|
3821
|
+
activeMatch = null;
|
|
3822
|
+
suggestions.close();
|
|
3823
|
+
}
|
|
3824
|
+
emit();
|
|
3825
|
+
},
|
|
3826
|
+
beginEdit({ value: editValue, tokens: editTokens, messageId }) {
|
|
3827
|
+
if (destroyed || disabled) return;
|
|
3828
|
+
preEditSnapshot = { value, tokens: [...tokens], selection, attachments: [...attachments] };
|
|
3829
|
+
mode = "edit";
|
|
3830
|
+
editingMessageId = messageId;
|
|
3831
|
+
value = editValue;
|
|
3832
|
+
tokens = [...editTokens ?? []];
|
|
3833
|
+
selection = { start: value.length, end: value.length };
|
|
3834
|
+
activeMatch = null;
|
|
3835
|
+
dismissed = [];
|
|
3836
|
+
suggestions.close();
|
|
3837
|
+
emit();
|
|
3838
|
+
},
|
|
3839
|
+
cancelEdit() {
|
|
3840
|
+
if (destroyed || mode !== "edit") return;
|
|
3841
|
+
const snapshot = preEditSnapshot;
|
|
3842
|
+
mode = "compose";
|
|
3843
|
+
editingMessageId = void 0;
|
|
3844
|
+
preEditSnapshot = null;
|
|
3845
|
+
if (snapshot) {
|
|
3846
|
+
value = snapshot.value;
|
|
3847
|
+
tokens = snapshot.tokens;
|
|
3848
|
+
selection = snapshot.selection;
|
|
3849
|
+
attachments = snapshot.attachments;
|
|
3850
|
+
}
|
|
3851
|
+
activeMatch = null;
|
|
3852
|
+
suggestions.close();
|
|
3853
|
+
emit();
|
|
3854
|
+
},
|
|
3855
|
+
copySelection() {
|
|
3856
|
+
return value.slice(selection.start, selection.end);
|
|
3857
|
+
},
|
|
3858
|
+
cutSelection() {
|
|
3859
|
+
if (destroyed || disabled || readOnly) return "";
|
|
3860
|
+
if (selection.start === selection.end) return "";
|
|
3861
|
+
const range = expandRangeOverTokens(tokens, selection);
|
|
3862
|
+
const text = value.slice(range.start, range.end);
|
|
3863
|
+
clipShadow = {
|
|
3864
|
+
text,
|
|
3865
|
+
tokens: tokens.filter((t) => t.start >= range.start && t.end <= range.end).map((t) => ({ ...t, start: t.start - range.start, end: t.end - range.start }))
|
|
3866
|
+
};
|
|
3867
|
+
const nextText = value.slice(0, range.start) + value.slice(range.end);
|
|
3868
|
+
mutateValue(nextText, { start: range.start, end: range.start });
|
|
3869
|
+
return text;
|
|
3870
|
+
},
|
|
3871
|
+
pasteText(text) {
|
|
3872
|
+
if (destroyed || disabled || readOnly) return;
|
|
3873
|
+
const shadow = clipShadow;
|
|
3874
|
+
const range = expandRangeOverTokens(tokens, selection);
|
|
3875
|
+
const nextText = value.slice(0, range.start) + text + value.slice(range.end);
|
|
3876
|
+
const caret = range.start + text.length;
|
|
3877
|
+
const before = value;
|
|
3878
|
+
mutateValue(nextText, { start: caret, end: caret }, { trimEventOnClamp: true });
|
|
3879
|
+
if (shadow && text === shadow.text && value === before.slice(0, range.start) + text + before.slice(range.end)) {
|
|
3880
|
+
const restored = shadow.tokens.map((t) => ({
|
|
3881
|
+
...t,
|
|
3882
|
+
start: t.start + range.start,
|
|
3883
|
+
end: t.end + range.start
|
|
3884
|
+
}));
|
|
3885
|
+
tokens = [...tokens, ...restored].sort((a, b) => a.start - b.start);
|
|
3886
|
+
emit();
|
|
3887
|
+
}
|
|
3888
|
+
},
|
|
3889
|
+
submit() {
|
|
3890
|
+
if (destroyed) return null;
|
|
3891
|
+
return performSubmit();
|
|
3892
|
+
},
|
|
3893
|
+
reset() {
|
|
3894
|
+
if (destroyed) return;
|
|
3895
|
+
cancelDraftWrite();
|
|
3896
|
+
suggestions.close();
|
|
3897
|
+
value = config.initialValue ?? "";
|
|
3898
|
+
tokens = [...config.initialTokens ?? []];
|
|
3899
|
+
selection = { start: value.length, end: value.length };
|
|
3900
|
+
isComposing = false;
|
|
3901
|
+
isBusy = false;
|
|
3902
|
+
error = null;
|
|
3903
|
+
attachments = [];
|
|
3904
|
+
mode = "compose";
|
|
3905
|
+
editingMessageId = void 0;
|
|
3906
|
+
preEditSnapshot = null;
|
|
3907
|
+
activeMatch = null;
|
|
3908
|
+
dismissed = [];
|
|
3909
|
+
clipShadow = null;
|
|
3910
|
+
lastTypingAt = Number.NEGATIVE_INFINITY;
|
|
3911
|
+
recomputeTriggers();
|
|
3912
|
+
emit();
|
|
3913
|
+
},
|
|
3914
|
+
serialize() {
|
|
3915
|
+
return serializeTokens(value, tokens);
|
|
3916
|
+
},
|
|
3917
|
+
destroy() {
|
|
3918
|
+
if (destroyed) return;
|
|
3919
|
+
cancelDraftWrite();
|
|
3920
|
+
suggestions.destroy();
|
|
3921
|
+
listeners.clear();
|
|
3922
|
+
destroyed = true;
|
|
3923
|
+
}
|
|
3924
|
+
};
|
|
3925
|
+
return api;
|
|
3926
|
+
}
|
|
3927
|
+
var composerSurfaceVariants = cva({
|
|
3928
|
+
base: [
|
|
3929
|
+
"overflow-hidden rounded-2xl border border-border bg-background shadow-sm",
|
|
3930
|
+
"transition-shadow focus-within:border-foreground/25 focus-within:shadow-md"
|
|
3931
|
+
].join(" "),
|
|
3932
|
+
variants: {
|
|
3933
|
+
disabled: {
|
|
3934
|
+
true: "pointer-events-none opacity-60",
|
|
3935
|
+
false: ""
|
|
3936
|
+
},
|
|
3937
|
+
error: {
|
|
3938
|
+
true: "border-destructive/50",
|
|
3939
|
+
false: ""
|
|
3940
|
+
}
|
|
3941
|
+
},
|
|
3942
|
+
defaultVariants: {
|
|
3943
|
+
disabled: "false",
|
|
3944
|
+
error: "false"
|
|
3945
|
+
}
|
|
3946
|
+
});
|
|
3947
|
+
var composerFieldClass = "block w-full resize-none bg-transparent px-3.5 py-3 text-sm placeholder:text-muted-foreground focus:outline-none";
|
|
3948
|
+
var composerTrayClass = "flex flex-wrap gap-2 px-3 pt-3";
|
|
3949
|
+
var composerAttachmentChipVariants = cva({
|
|
3950
|
+
base: "inline-flex items-center gap-1 rounded-md bg-muted px-2 py-0.5 text-xs",
|
|
3951
|
+
variants: {
|
|
3952
|
+
status: {
|
|
3953
|
+
pending: "opacity-70",
|
|
3954
|
+
uploading: "opacity-70",
|
|
3955
|
+
ready: "",
|
|
3956
|
+
error: "text-destructive"
|
|
3957
|
+
}
|
|
3958
|
+
},
|
|
3959
|
+
defaultVariants: {
|
|
3960
|
+
status: "pending"
|
|
3961
|
+
}
|
|
3962
|
+
});
|
|
3963
|
+
var composerTokenPillClass = "rounded bg-accent/40 px-0.5 text-accent-foreground";
|
|
3964
|
+
var composerMenuClass = "z-20 w-72 overflow-hidden rounded-xl border border-border bg-popover shadow-lg";
|
|
3965
|
+
var composerMenuItemVariants = cva({
|
|
3966
|
+
base: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm",
|
|
3967
|
+
variants: {
|
|
3968
|
+
active: {
|
|
3969
|
+
true: "bg-accent",
|
|
3970
|
+
false: "hover:bg-accent/50"
|
|
3971
|
+
}
|
|
3972
|
+
},
|
|
3973
|
+
defaultVariants: {
|
|
3974
|
+
active: "false"
|
|
3975
|
+
}
|
|
3976
|
+
});
|
|
3977
|
+
var composerCounterVariants = cva({
|
|
3978
|
+
base: "text-xs tabular-nums",
|
|
3979
|
+
variants: {
|
|
3980
|
+
overLimit: {
|
|
3981
|
+
true: "font-medium text-destructive",
|
|
3982
|
+
false: "text-muted-foreground"
|
|
3983
|
+
}
|
|
3984
|
+
},
|
|
3985
|
+
defaultVariants: {
|
|
3986
|
+
overLimit: "false"
|
|
3987
|
+
}
|
|
3988
|
+
});
|
|
3989
|
+
var composerPrimaryActionVariants = cva({
|
|
3990
|
+
base: "flex h-9 w-9 items-center justify-center rounded-full transition",
|
|
3991
|
+
variants: {
|
|
3992
|
+
enabled: {
|
|
3993
|
+
true: "bg-primary text-primary-foreground hover:opacity-90",
|
|
3994
|
+
false: "bg-muted text-muted-foreground"
|
|
3995
|
+
}
|
|
3996
|
+
},
|
|
3997
|
+
defaultVariants: {
|
|
3998
|
+
enabled: "false"
|
|
3999
|
+
}
|
|
4000
|
+
});
|
|
4001
|
+
function useComposer(config = {}, init) {
|
|
4002
|
+
const configRef = React11.useRef(config);
|
|
4003
|
+
const initRef = React11.useRef(init);
|
|
4004
|
+
const coreRef = React11.useRef(null);
|
|
4005
|
+
const getCore = React11.useCallback(() => {
|
|
4006
|
+
if (coreRef.current === null) {
|
|
4007
|
+
const api = createComposer(configRef.current);
|
|
4008
|
+
initRef.current?.(api);
|
|
4009
|
+
coreRef.current = { api, snapshot: api.getState() };
|
|
4010
|
+
}
|
|
4011
|
+
return coreRef.current;
|
|
4012
|
+
}, []);
|
|
4013
|
+
const subscribe = React11.useCallback(
|
|
4014
|
+
(onStoreChange) => {
|
|
4015
|
+
const core = getCore();
|
|
4016
|
+
return core.api.subscribe((next) => {
|
|
4017
|
+
core.snapshot = next;
|
|
4018
|
+
onStoreChange();
|
|
4019
|
+
});
|
|
4020
|
+
},
|
|
4021
|
+
[getCore]
|
|
4022
|
+
);
|
|
4023
|
+
const getSnapshot = React11.useCallback(() => getCore().snapshot, [getCore]);
|
|
4024
|
+
const state = React11.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
4025
|
+
React11.useEffect(
|
|
4026
|
+
() => () => {
|
|
4027
|
+
coreRef.current?.api.destroy();
|
|
4028
|
+
coreRef.current = null;
|
|
4029
|
+
},
|
|
4030
|
+
[]
|
|
4031
|
+
);
|
|
4032
|
+
return { state, api: getCore().api };
|
|
4033
|
+
}
|
|
4034
|
+
var FIELD_LINE_HEIGHT = 1.5;
|
|
4035
|
+
var FIELD_VERTICAL_PADDING_REM = 1.5;
|
|
4036
|
+
var TRIMMED_NOTICE_HIDE_MS = 4e3;
|
|
4037
|
+
function fieldHeightFor(lines) {
|
|
4038
|
+
return `calc(${lines * FIELD_LINE_HEIGHT}em + ${FIELD_VERTICAL_PADDING_REM}rem)`;
|
|
4039
|
+
}
|
|
4040
|
+
var DEFAULT_COMPOSER_STRINGS = {
|
|
4041
|
+
composerLabel: "Message composer",
|
|
4042
|
+
messageLabel: "Message",
|
|
4043
|
+
sendLabel: "Send",
|
|
4044
|
+
stopLabel: "Stop",
|
|
4045
|
+
attachLabel: "Attach a file",
|
|
4046
|
+
removeAttachmentLabel: (name) => `Remove attachment ${name}`,
|
|
4047
|
+
suggestionsLabel: "Suggestions",
|
|
4048
|
+
noMatchesLabel: (query) => `No matches for "${query}"`,
|
|
4049
|
+
loadingLabel: "Loading suggestions\u2026",
|
|
4050
|
+
retryLabel: "Retry",
|
|
4051
|
+
trimmedNotice: "Pasted text was trimmed to fit the length limit",
|
|
4052
|
+
counterLabel: (remaining) => `${remaining} characters remaining`,
|
|
4053
|
+
editingLabel: "Editing message",
|
|
4054
|
+
cancelEditLabel: "Cancel edit",
|
|
4055
|
+
resultsAnnouncement: (count) => `${count} suggestions available`
|
|
4056
|
+
};
|
|
4057
|
+
function useLatestRef(value) {
|
|
4058
|
+
const ref = React11.useRef(value);
|
|
4059
|
+
ref.current = value;
|
|
4060
|
+
return ref;
|
|
4061
|
+
}
|
|
4062
|
+
function kindFromMime(mimeType) {
|
|
4063
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
4064
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
4065
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
4066
|
+
return "file";
|
|
4067
|
+
}
|
|
4068
|
+
function segmentValue(value, tokens) {
|
|
4069
|
+
const segments = [];
|
|
4070
|
+
let cursor = 0;
|
|
4071
|
+
for (const token of tokens) {
|
|
4072
|
+
if (token.start > cursor) {
|
|
4073
|
+
segments.push({ key: `p${cursor}`, text: value.slice(cursor, token.start), isToken: false });
|
|
4074
|
+
}
|
|
4075
|
+
segments.push({ key: `t${token.start}`, text: value.slice(token.start, token.end), isToken: true });
|
|
4076
|
+
cursor = token.end;
|
|
4077
|
+
}
|
|
4078
|
+
if (cursor < value.length) {
|
|
4079
|
+
segments.push({ key: `p${cursor}`, text: value.slice(cursor), isToken: false });
|
|
4080
|
+
}
|
|
4081
|
+
return segments;
|
|
4082
|
+
}
|
|
4083
|
+
var iconSvgProps = {
|
|
4084
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4085
|
+
viewBox: "0 0 24 24",
|
|
4086
|
+
width: 16,
|
|
4087
|
+
height: 16,
|
|
4088
|
+
fill: "none",
|
|
4089
|
+
stroke: "currentColor",
|
|
4090
|
+
strokeWidth: 2,
|
|
4091
|
+
strokeLinecap: "round",
|
|
4092
|
+
strokeLinejoin: "round",
|
|
4093
|
+
"aria-hidden": true
|
|
4094
|
+
};
|
|
4095
|
+
function IconArrowUp() {
|
|
4096
|
+
return /* @__PURE__ */ jsxs("svg", { ...iconSvgProps, children: [
|
|
4097
|
+
/* @__PURE__ */ jsx("path", { d: "M12 19V5" }),
|
|
4098
|
+
/* @__PURE__ */ jsx("path", { d: "m5 12 7-7 7 7" })
|
|
4099
|
+
] });
|
|
4100
|
+
}
|
|
4101
|
+
function IconStop() {
|
|
4102
|
+
return /* @__PURE__ */ jsx("svg", { ...iconSvgProps, children: /* @__PURE__ */ jsx("rect", { x: 7, y: 7, width: 10, height: 10, rx: 1.5 }) });
|
|
4103
|
+
}
|
|
4104
|
+
var RefractionComposer = React11.forwardRef(
|
|
4105
|
+
({
|
|
4106
|
+
value: valueProp,
|
|
4107
|
+
defaultValue,
|
|
4108
|
+
onChange,
|
|
4109
|
+
placeholder,
|
|
4110
|
+
disabledPlaceholder,
|
|
4111
|
+
minLines = 1,
|
|
4112
|
+
maxLines = 6,
|
|
4113
|
+
maxLength,
|
|
4114
|
+
maxAttachments,
|
|
4115
|
+
disabled = false,
|
|
4116
|
+
readOnly = false,
|
|
4117
|
+
busy = false,
|
|
4118
|
+
onStop,
|
|
4119
|
+
autoFocus,
|
|
4120
|
+
dir,
|
|
4121
|
+
triggers,
|
|
4122
|
+
submitOnEnter,
|
|
4123
|
+
strings: stringsProp,
|
|
4124
|
+
leading,
|
|
4125
|
+
trailing,
|
|
4126
|
+
primaryAction,
|
|
4127
|
+
renderSuggestion,
|
|
4128
|
+
initialAttachments,
|
|
4129
|
+
draftStore,
|
|
4130
|
+
draftKey,
|
|
4131
|
+
validator,
|
|
4132
|
+
replyToMessageId,
|
|
4133
|
+
onSubmit,
|
|
4134
|
+
onEditLastRequested,
|
|
4135
|
+
onEditCancel,
|
|
4136
|
+
onTypingActivity,
|
|
4137
|
+
onAttachmentAdd,
|
|
4138
|
+
onAttachmentRejected,
|
|
4139
|
+
onEvent,
|
|
4140
|
+
apiRef,
|
|
4141
|
+
id,
|
|
4142
|
+
className,
|
|
4143
|
+
...rest
|
|
4144
|
+
}, forwardedRef) => {
|
|
4145
|
+
const strings = React11.useMemo(
|
|
4146
|
+
() => ({ ...DEFAULT_COMPOSER_STRINGS, ...stringsProp }),
|
|
4147
|
+
[stringsProp]
|
|
4148
|
+
);
|
|
4149
|
+
const onSubmitRef = useLatestRef(onSubmit);
|
|
4150
|
+
const onChangeRef = useLatestRef(onChange);
|
|
4151
|
+
const onStopRef = useLatestRef(onStop);
|
|
4152
|
+
const onEventRef = useLatestRef(onEvent);
|
|
4153
|
+
const onTypingActivityRef = useLatestRef(onTypingActivity);
|
|
4154
|
+
const onAttachmentAddRef = useLatestRef(onAttachmentAdd);
|
|
4155
|
+
const onAttachmentRejectedRef = useLatestRef(onAttachmentRejected);
|
|
4156
|
+
const onEditLastRequestedRef = useLatestRef(onEditLastRequested);
|
|
4157
|
+
const onEditCancelRef = useLatestRef(onEditCancel);
|
|
4158
|
+
const [trimmedNoticeVisible, setTrimmedNoticeVisible] = React11.useState(false);
|
|
4159
|
+
const trimmedTimerRef = React11.useRef(null);
|
|
4160
|
+
const configRef = React11.useRef(null);
|
|
4161
|
+
if (configRef.current === null) {
|
|
4162
|
+
configRef.current = {
|
|
4163
|
+
initialValue: valueProp ?? defaultValue ?? "",
|
|
4164
|
+
minLines,
|
|
4165
|
+
maxLines,
|
|
4166
|
+
triggers,
|
|
4167
|
+
onEvent: (event) => {
|
|
4168
|
+
if (event.type === "typing") onTypingActivityRef.current?.();
|
|
4169
|
+
if (event.type === "attachment-rejected") onAttachmentRejectedRef.current?.(event);
|
|
4170
|
+
if (event.type === "paste-trimmed") {
|
|
4171
|
+
setTrimmedNoticeVisible(true);
|
|
4172
|
+
if (trimmedTimerRef.current !== null) clearTimeout(trimmedTimerRef.current);
|
|
4173
|
+
trimmedTimerRef.current = setTimeout(() => {
|
|
4174
|
+
trimmedTimerRef.current = null;
|
|
4175
|
+
setTrimmedNoticeVisible(false);
|
|
4176
|
+
}, TRIMMED_NOTICE_HIDE_MS);
|
|
4177
|
+
}
|
|
4178
|
+
onEventRef.current?.(event);
|
|
4179
|
+
}
|
|
4180
|
+
};
|
|
4181
|
+
}
|
|
4182
|
+
configRef.current.maxLength = maxLength;
|
|
4183
|
+
configRef.current.maxAttachments = maxAttachments;
|
|
4184
|
+
configRef.current.validator = validator;
|
|
4185
|
+
configRef.current.replyToMessageId = replyToMessageId;
|
|
4186
|
+
configRef.current.draftStore = draftStore;
|
|
4187
|
+
configRef.current.draftKey = draftKey;
|
|
4188
|
+
const { state, api } = useComposer(configRef.current, (core) => {
|
|
4189
|
+
for (const draft of initialAttachments ?? []) core.addAttachment(draft);
|
|
4190
|
+
if (disabled) core.setDisabled(true);
|
|
4191
|
+
if (readOnly) core.setReadOnly(true);
|
|
4192
|
+
if (busy) core.setBusy(true);
|
|
4193
|
+
});
|
|
4194
|
+
React11.useEffect(() => () => {
|
|
4195
|
+
if (trimmedTimerRef.current !== null) clearTimeout(trimmedTimerRef.current);
|
|
4196
|
+
}, []);
|
|
4197
|
+
const textareaRef = React11.useRef(null);
|
|
4198
|
+
const highlightRef = React11.useRef(null);
|
|
4199
|
+
const mergedTextareaRef = React11.useCallback(
|
|
4200
|
+
(node) => {
|
|
4201
|
+
textareaRef.current = node;
|
|
4202
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
4203
|
+
else if (forwardedRef) forwardedRef.current = node;
|
|
4204
|
+
},
|
|
4205
|
+
[forwardedRef]
|
|
4206
|
+
);
|
|
4207
|
+
const idBase = React11.useRef(id ?? generateId("composer")).current;
|
|
4208
|
+
const listId = `${idBase}-listbox`;
|
|
4209
|
+
const optionId = (index) => `${idBase}-option-${index}`;
|
|
4210
|
+
React11.useEffect(() => {
|
|
4211
|
+
if (!apiRef) return;
|
|
4212
|
+
if (typeof apiRef === "function") {
|
|
4213
|
+
apiRef(api);
|
|
4214
|
+
return () => {
|
|
4215
|
+
apiRef(null);
|
|
4216
|
+
};
|
|
4217
|
+
}
|
|
4218
|
+
const mutableRef = apiRef;
|
|
4219
|
+
mutableRef.current = api;
|
|
4220
|
+
return () => {
|
|
4221
|
+
mutableRef.current = null;
|
|
4222
|
+
};
|
|
4223
|
+
}, [apiRef, api]);
|
|
4224
|
+
React11.useEffect(() => {
|
|
4225
|
+
api.setDisabled(disabled);
|
|
4226
|
+
}, [api, disabled]);
|
|
4227
|
+
React11.useEffect(() => {
|
|
4228
|
+
api.setReadOnly(readOnly);
|
|
4229
|
+
}, [api, readOnly]);
|
|
4230
|
+
React11.useEffect(() => {
|
|
4231
|
+
api.setBusy(busy);
|
|
4232
|
+
}, [api, busy]);
|
|
4233
|
+
React11.useEffect(() => {
|
|
4234
|
+
if (valueProp === void 0) return;
|
|
4235
|
+
const current = api.getState();
|
|
4236
|
+
if (current.disabled || current.readOnly || current.value === valueProp) return;
|
|
4237
|
+
api.setValue(
|
|
4238
|
+
valueProp,
|
|
4239
|
+
{ start: valueProp.length, end: valueProp.length },
|
|
4240
|
+
{ programmatic: true }
|
|
4241
|
+
);
|
|
4242
|
+
}, [api, valueProp, state.value]);
|
|
4243
|
+
const withValueChange = React11.useCallback(
|
|
4244
|
+
(mutate) => {
|
|
4245
|
+
const before = api.getState().value;
|
|
4246
|
+
const result = mutate();
|
|
4247
|
+
const after = api.getState().value;
|
|
4248
|
+
if (after !== before) onChangeRef.current?.(after);
|
|
4249
|
+
return result;
|
|
4250
|
+
},
|
|
4251
|
+
[api, onChangeRef]
|
|
4252
|
+
);
|
|
4253
|
+
const [coarsePointer, setCoarsePointer] = React11.useState(false);
|
|
4254
|
+
React11.useEffect(() => {
|
|
4255
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
4256
|
+
const query = window.matchMedia("(pointer: coarse)");
|
|
4257
|
+
const update = () => setCoarsePointer(query.matches);
|
|
4258
|
+
update();
|
|
4259
|
+
query.addEventListener?.("change", update);
|
|
4260
|
+
return () => query.removeEventListener?.("change", update);
|
|
4261
|
+
}, []);
|
|
4262
|
+
const submitEnabled = submitOnEnter ?? !coarsePointer;
|
|
4263
|
+
React11.useEffect(() => {
|
|
4264
|
+
const el = textareaRef.current;
|
|
4265
|
+
if (!el) return;
|
|
4266
|
+
if (el.value !== state.value) el.value = state.value;
|
|
4267
|
+
if (document.activeElement === el && (el.selectionStart !== state.selection.start || el.selectionEnd !== state.selection.end)) {
|
|
4268
|
+
el.setSelectionRange(state.selection.start, state.selection.end);
|
|
4269
|
+
}
|
|
4270
|
+
}, [state.value, state.selection.start, state.selection.end]);
|
|
4271
|
+
const readSelection = (el) => ({
|
|
4272
|
+
start: el.selectionStart ?? el.value.length,
|
|
4273
|
+
end: el.selectionEnd ?? el.value.length
|
|
4274
|
+
});
|
|
4275
|
+
const handleChange = (event) => {
|
|
4276
|
+
const el = event.currentTarget;
|
|
4277
|
+
withValueChange(() => api.setValue(el.value, readSelection(el)));
|
|
4278
|
+
};
|
|
4279
|
+
const handleSelect = (event) => {
|
|
4280
|
+
const el = event.currentTarget;
|
|
4281
|
+
const next = readSelection(el);
|
|
4282
|
+
const current = api.getState().selection;
|
|
4283
|
+
if (next.start !== current.start || next.end !== current.end) {
|
|
4284
|
+
api.setSelection(next);
|
|
4285
|
+
}
|
|
4286
|
+
};
|
|
4287
|
+
const submitNow = React11.useCallback(() => {
|
|
4288
|
+
const submission = withValueChange(() => api.submit());
|
|
4289
|
+
if (submission) onSubmitRef.current?.(submission);
|
|
4290
|
+
return submission !== null;
|
|
4291
|
+
}, [api, onSubmitRef, withValueChange]);
|
|
4292
|
+
const handleKeyDown = (event) => {
|
|
4293
|
+
const snapshot = api.getState();
|
|
4294
|
+
const menuOpen2 = snapshot.suggestion.isOpen && !snapshot.isComposing;
|
|
4295
|
+
const hasMenuItems = snapshot.suggestion.items.length > 0;
|
|
4296
|
+
if (menuOpen2) {
|
|
4297
|
+
if (event.key === "ArrowDown" && hasMenuItems) {
|
|
4298
|
+
event.preventDefault();
|
|
4299
|
+
api.moveSuggestionNext();
|
|
4300
|
+
return;
|
|
4301
|
+
}
|
|
4302
|
+
if (event.key === "ArrowUp" && hasMenuItems) {
|
|
4303
|
+
event.preventDefault();
|
|
4304
|
+
api.moveSuggestionPrevious();
|
|
4305
|
+
return;
|
|
4306
|
+
}
|
|
4307
|
+
if (event.key === "Tab" && hasMenuItems) {
|
|
4308
|
+
event.preventDefault();
|
|
4309
|
+
withValueChange(() => api.applySuggestion());
|
|
4310
|
+
return;
|
|
4311
|
+
}
|
|
4312
|
+
if (event.key === "Escape") {
|
|
4313
|
+
event.preventDefault();
|
|
4314
|
+
api.dismissSuggestion();
|
|
4315
|
+
return;
|
|
4316
|
+
}
|
|
4317
|
+
}
|
|
4318
|
+
if (event.key === "Escape" && !menuOpen2 && snapshot.mode === "edit") {
|
|
4319
|
+
event.preventDefault();
|
|
4320
|
+
withValueChange(() => api.cancelEdit());
|
|
4321
|
+
onEditCancelRef.current?.();
|
|
4322
|
+
return;
|
|
4323
|
+
}
|
|
4324
|
+
if (event.key === "ArrowUp" && !menuOpen2 && !snapshot.isComposing && snapshot.value === "" && onEditLastRequestedRef.current) {
|
|
4325
|
+
event.preventDefault();
|
|
4326
|
+
onEditLastRequestedRef.current();
|
|
4327
|
+
return;
|
|
4328
|
+
}
|
|
4329
|
+
if (event.key === "Enter") {
|
|
4330
|
+
if (menuOpen2) {
|
|
4331
|
+
event.preventDefault();
|
|
4332
|
+
withValueChange(() => api.applyEnter({ shiftPressed: event.shiftKey }));
|
|
4333
|
+
return;
|
|
4334
|
+
}
|
|
4335
|
+
if (snapshot.isComposing) return;
|
|
4336
|
+
if (event.shiftKey || !submitEnabled) return;
|
|
4337
|
+
event.preventDefault();
|
|
4338
|
+
if (snapshot.disabled || snapshot.readOnly) return;
|
|
4339
|
+
submitNow();
|
|
4340
|
+
}
|
|
4341
|
+
};
|
|
4342
|
+
const handleCompositionStart = () => api.setComposing(true);
|
|
4343
|
+
const handleCompositionEnd = () => withValueChange(() => api.setComposing(false));
|
|
4344
|
+
const handleCopy = (event) => {
|
|
4345
|
+
const text = api.copySelection();
|
|
4346
|
+
if (text === "") return;
|
|
4347
|
+
event.preventDefault();
|
|
4348
|
+
event.clipboardData.setData("text/plain", text);
|
|
4349
|
+
};
|
|
4350
|
+
const handleCut = (event) => {
|
|
4351
|
+
event.preventDefault();
|
|
4352
|
+
const text = withValueChange(() => api.cutSelection());
|
|
4353
|
+
if (text !== "") event.clipboardData.setData("text/plain", text);
|
|
4354
|
+
};
|
|
4355
|
+
const addFiles = React11.useCallback(
|
|
4356
|
+
(files) => {
|
|
4357
|
+
for (const file of Array.from(files)) {
|
|
4358
|
+
const previewUrl = typeof URL !== "undefined" && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : void 0;
|
|
4359
|
+
const attachmentId = api.addAttachment({
|
|
4360
|
+
kind: kindFromMime(file.type),
|
|
4361
|
+
name: file.name,
|
|
4362
|
+
mimeType: file.type || void 0,
|
|
4363
|
+
sizeBytes: file.size,
|
|
4364
|
+
previewUrl
|
|
4365
|
+
});
|
|
4366
|
+
if (attachmentId === null) {
|
|
4367
|
+
if (previewUrl !== void 0) URL.revokeObjectURL(previewUrl);
|
|
4368
|
+
continue;
|
|
4369
|
+
}
|
|
4370
|
+
const added = api.getState().attachments.find((a) => a.id === attachmentId);
|
|
4371
|
+
if (added) onAttachmentAddRef.current?.(added);
|
|
4372
|
+
}
|
|
4373
|
+
},
|
|
4374
|
+
[api, onAttachmentAddRef]
|
|
4375
|
+
);
|
|
4376
|
+
const handlePaste = (event) => {
|
|
4377
|
+
const files = event.clipboardData?.files;
|
|
4378
|
+
if (files && files.length > 0) {
|
|
4379
|
+
event.preventDefault();
|
|
4380
|
+
addFiles(files);
|
|
4381
|
+
return;
|
|
4382
|
+
}
|
|
4383
|
+
event.preventDefault();
|
|
4384
|
+
withValueChange(() => api.pasteText(event.clipboardData?.getData("text/plain") ?? ""));
|
|
4385
|
+
};
|
|
4386
|
+
const [dragActive, setDragActive] = React11.useState(false);
|
|
4387
|
+
const dragHasPayload = (event) => {
|
|
4388
|
+
const types = event.dataTransfer ? Array.from(event.dataTransfer.types ?? []) : [];
|
|
4389
|
+
return types.includes("Files") || types.includes("text/plain");
|
|
4390
|
+
};
|
|
4391
|
+
const handleDragOver = (event) => {
|
|
4392
|
+
if (!dragHasPayload(event)) return;
|
|
4393
|
+
event.preventDefault();
|
|
4394
|
+
setDragActive(true);
|
|
4395
|
+
};
|
|
4396
|
+
const handleDragLeave = () => setDragActive(false);
|
|
4397
|
+
const handleDrop = (event) => {
|
|
4398
|
+
event.preventDefault();
|
|
4399
|
+
setDragActive(false);
|
|
4400
|
+
const transfer = event.dataTransfer;
|
|
4401
|
+
if (!transfer) return;
|
|
4402
|
+
if (transfer.files && transfer.files.length > 0) {
|
|
4403
|
+
addFiles(transfer.files);
|
|
4404
|
+
return;
|
|
4405
|
+
}
|
|
4406
|
+
const text = transfer.getData("text/plain");
|
|
4407
|
+
if (text) withValueChange(() => api.pasteText(text));
|
|
4408
|
+
};
|
|
4409
|
+
const handleBlur = () => api.dismissSuggestionDeferred();
|
|
4410
|
+
const handleScroll = (event) => {
|
|
4411
|
+
if (highlightRef.current) {
|
|
4412
|
+
highlightRef.current.scrollTop = event.currentTarget.scrollTop;
|
|
4413
|
+
}
|
|
4414
|
+
};
|
|
4415
|
+
const hasTriggers = (triggers?.length ?? 0) > 0;
|
|
4416
|
+
const menuOpen = state.suggestion.isOpen;
|
|
4417
|
+
const visibleItems = state.suggestion.visibleItems;
|
|
4418
|
+
const activeIndex = state.suggestion.activeIndex;
|
|
4419
|
+
const hasText = state.value.trim().length > 0;
|
|
4420
|
+
const effectivePlaceholder = state.disabled && disabledPlaceholder !== void 0 ? disabledPlaceholder : placeholder;
|
|
4421
|
+
const segments = React11.useMemo(
|
|
4422
|
+
() => segmentValue(state.value, state.tokens),
|
|
4423
|
+
[state.value, state.tokens]
|
|
4424
|
+
);
|
|
4425
|
+
const primaryContext = {
|
|
4426
|
+
hasText,
|
|
4427
|
+
canSend: state.canSend,
|
|
4428
|
+
busy: state.isBusy
|
|
4429
|
+
};
|
|
4430
|
+
const defaultPrimaryAction = state.isBusy ? /* @__PURE__ */ jsx(
|
|
4431
|
+
"button",
|
|
4432
|
+
{
|
|
4433
|
+
type: "button",
|
|
4434
|
+
"aria-label": strings.stopLabel,
|
|
4435
|
+
className: composerPrimaryActionVariants({ enabled: "true" }),
|
|
4436
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
4437
|
+
onClick: () => onStopRef.current?.(),
|
|
4438
|
+
children: /* @__PURE__ */ jsx(IconStop, {})
|
|
4439
|
+
}
|
|
4440
|
+
) : /* @__PURE__ */ jsx(
|
|
4441
|
+
"button",
|
|
4442
|
+
{
|
|
4443
|
+
type: "button",
|
|
4444
|
+
"aria-label": strings.sendLabel,
|
|
4445
|
+
disabled: !state.canSend,
|
|
4446
|
+
className: composerPrimaryActionVariants({ enabled: state.canSend ? "true" : "false" }),
|
|
4447
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
4448
|
+
onClick: submitNow,
|
|
4449
|
+
children: /* @__PURE__ */ jsx(IconArrowUp, {})
|
|
4450
|
+
}
|
|
4451
|
+
);
|
|
4452
|
+
const menuBody = () => {
|
|
4453
|
+
if (state.suggestion.loading) {
|
|
4454
|
+
return /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-sm text-muted-foreground", children: strings.loadingLabel });
|
|
4455
|
+
}
|
|
4456
|
+
if (state.suggestion.error !== null) {
|
|
4457
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 text-sm text-destructive", children: [
|
|
4458
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: state.suggestion.error }),
|
|
4459
|
+
/* @__PURE__ */ jsx(
|
|
4460
|
+
"button",
|
|
4461
|
+
{
|
|
4462
|
+
type: "button",
|
|
4463
|
+
className: "font-medium underline",
|
|
4464
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
4465
|
+
onClick: () => api.retrySuggestions(),
|
|
4466
|
+
children: strings.retryLabel
|
|
4467
|
+
}
|
|
4468
|
+
)
|
|
4469
|
+
] });
|
|
4470
|
+
}
|
|
4471
|
+
if (visibleItems.length === 0) {
|
|
4472
|
+
return /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-sm text-muted-foreground", children: strings.noMatchesLabel(state.activeTrigger?.query ?? "") });
|
|
4473
|
+
}
|
|
4474
|
+
return visibleItems.map((candidate, index) => {
|
|
4475
|
+
const active = index === activeIndex;
|
|
4476
|
+
return /* @__PURE__ */ jsx(
|
|
4477
|
+
"button",
|
|
4478
|
+
{
|
|
4479
|
+
type: "button",
|
|
4480
|
+
role: "option",
|
|
4481
|
+
id: optionId(index),
|
|
4482
|
+
"aria-selected": active,
|
|
4483
|
+
className: composerMenuItemVariants({ active: active ? "true" : "false" }),
|
|
4484
|
+
onMouseEnter: () => api.setSuggestionActiveIndex(index),
|
|
4485
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
4486
|
+
onClick: () => withValueChange(() => api.applySuggestion(index)),
|
|
4487
|
+
children: renderSuggestion ? renderSuggestion(candidate, { active, index }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4488
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: candidate.display }),
|
|
4489
|
+
candidate.subtitle !== void 0 && /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: candidate.subtitle })
|
|
4490
|
+
] })
|
|
4491
|
+
},
|
|
4492
|
+
candidate.id
|
|
4493
|
+
);
|
|
4494
|
+
});
|
|
4495
|
+
};
|
|
4496
|
+
return /* @__PURE__ */ jsxs(
|
|
4497
|
+
"div",
|
|
4498
|
+
{
|
|
4499
|
+
...rest,
|
|
4500
|
+
id: idBase,
|
|
4501
|
+
dir,
|
|
4502
|
+
role: "form",
|
|
4503
|
+
"aria-label": strings.composerLabel,
|
|
4504
|
+
className: cn("relative", className),
|
|
4505
|
+
onDragOver: handleDragOver,
|
|
4506
|
+
onDragLeave: handleDragLeave,
|
|
4507
|
+
onDrop: handleDrop,
|
|
4508
|
+
children: [
|
|
4509
|
+
menuOpen && /* @__PURE__ */ jsx(
|
|
4510
|
+
"div",
|
|
4511
|
+
{
|
|
4512
|
+
id: listId,
|
|
4513
|
+
role: "listbox",
|
|
4514
|
+
"aria-label": strings.suggestionsLabel,
|
|
4515
|
+
className: cn(composerMenuClass, "absolute bottom-full start-0 mb-2"),
|
|
4516
|
+
children: menuBody()
|
|
4517
|
+
}
|
|
4518
|
+
),
|
|
4519
|
+
/* @__PURE__ */ jsxs(
|
|
4520
|
+
"div",
|
|
4521
|
+
{
|
|
4522
|
+
"data-dragover": dragActive ? "" : void 0,
|
|
4523
|
+
className: cn(
|
|
4524
|
+
composerSurfaceVariants({
|
|
4525
|
+
disabled: state.disabled ? "true" : "false",
|
|
4526
|
+
error: state.error !== null ? "true" : "false"
|
|
4527
|
+
}),
|
|
4528
|
+
dragActive && "border-primary/60 shadow-md"
|
|
4529
|
+
),
|
|
4530
|
+
children: [
|
|
4531
|
+
state.error !== null && /* @__PURE__ */ jsx(
|
|
4532
|
+
"div",
|
|
4533
|
+
{
|
|
4534
|
+
role: "alert",
|
|
4535
|
+
className: "flex items-center gap-2 border-b border-border bg-destructive/5 px-3 py-2 text-xs text-destructive",
|
|
4536
|
+
children: /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: state.error })
|
|
4537
|
+
}
|
|
4538
|
+
),
|
|
4539
|
+
state.mode === "edit" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2 text-xs text-muted-foreground", children: [
|
|
4540
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: strings.editingLabel }),
|
|
4541
|
+
/* @__PURE__ */ jsx(
|
|
4542
|
+
"button",
|
|
4543
|
+
{
|
|
4544
|
+
type: "button",
|
|
4545
|
+
className: "font-medium underline",
|
|
4546
|
+
onClick: () => {
|
|
4547
|
+
withValueChange(() => api.cancelEdit());
|
|
4548
|
+
onEditCancelRef.current?.();
|
|
4549
|
+
},
|
|
4550
|
+
children: strings.cancelEditLabel
|
|
4551
|
+
}
|
|
4552
|
+
)
|
|
4553
|
+
] }),
|
|
4554
|
+
trimmedNoticeVisible && /* @__PURE__ */ jsx("div", { role: "status", className: "px-3 pt-2 text-xs text-muted-foreground", children: strings.trimmedNotice }),
|
|
4555
|
+
state.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: composerTrayClass, children: state.attachments.map((attachment) => /* @__PURE__ */ jsxs(
|
|
4556
|
+
"span",
|
|
4557
|
+
{
|
|
4558
|
+
className: composerAttachmentChipVariants({ status: attachment.status }),
|
|
4559
|
+
children: [
|
|
4560
|
+
attachment.name,
|
|
4561
|
+
/* @__PURE__ */ jsx(
|
|
4562
|
+
"button",
|
|
4563
|
+
{
|
|
4564
|
+
type: "button",
|
|
4565
|
+
"aria-label": strings.removeAttachmentLabel(attachment.name),
|
|
4566
|
+
className: "text-muted-foreground hover:text-destructive",
|
|
4567
|
+
onClick: () => {
|
|
4568
|
+
api.removeAttachment(attachment.id);
|
|
4569
|
+
if (attachment.previewUrl !== void 0 && typeof URL !== "undefined" && typeof URL.revokeObjectURL === "function") {
|
|
4570
|
+
URL.revokeObjectURL(attachment.previewUrl);
|
|
4571
|
+
}
|
|
4572
|
+
},
|
|
4573
|
+
children: "\u2715"
|
|
4574
|
+
}
|
|
4575
|
+
)
|
|
4576
|
+
]
|
|
4577
|
+
},
|
|
4578
|
+
attachment.id
|
|
4579
|
+
)) }),
|
|
4580
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
4581
|
+
/* @__PURE__ */ jsxs(
|
|
4582
|
+
"div",
|
|
4583
|
+
{
|
|
4584
|
+
ref: highlightRef,
|
|
4585
|
+
"aria-hidden": "true",
|
|
4586
|
+
className: cn(
|
|
4587
|
+
composerFieldClass,
|
|
4588
|
+
"pointer-events-none overflow-hidden whitespace-pre-wrap break-words text-transparent"
|
|
4589
|
+
),
|
|
4590
|
+
style: {
|
|
4591
|
+
lineHeight: FIELD_LINE_HEIGHT,
|
|
4592
|
+
minHeight: fieldHeightFor(minLines),
|
|
4593
|
+
maxHeight: fieldHeightFor(maxLines)
|
|
4594
|
+
},
|
|
4595
|
+
children: [
|
|
4596
|
+
segments.map(
|
|
4597
|
+
(segment) => segment.isToken ? /* @__PURE__ */ jsx(
|
|
4598
|
+
"span",
|
|
4599
|
+
{
|
|
4600
|
+
"data-token": "",
|
|
4601
|
+
className: cn(composerTokenPillClass, "px-0 text-transparent"),
|
|
4602
|
+
children: /* @__PURE__ */ jsx("bdi", { children: segment.text })
|
|
4603
|
+
},
|
|
4604
|
+
segment.key
|
|
4605
|
+
) : /* @__PURE__ */ jsx("span", { children: segment.text }, segment.key)
|
|
4606
|
+
),
|
|
4607
|
+
"\u200B"
|
|
4608
|
+
]
|
|
4609
|
+
}
|
|
4610
|
+
),
|
|
4611
|
+
/* @__PURE__ */ jsx(
|
|
4612
|
+
"textarea",
|
|
4613
|
+
{
|
|
4614
|
+
ref: mergedTextareaRef,
|
|
4615
|
+
id: `${idBase}-input`,
|
|
4616
|
+
rows: minLines,
|
|
4617
|
+
value: state.value,
|
|
4618
|
+
placeholder: effectivePlaceholder,
|
|
4619
|
+
disabled: state.disabled,
|
|
4620
|
+
readOnly: state.readOnly,
|
|
4621
|
+
autoFocus,
|
|
4622
|
+
"aria-multiline": "true",
|
|
4623
|
+
"aria-label": strings.messageLabel,
|
|
4624
|
+
...hasTriggers ? {
|
|
4625
|
+
"aria-autocomplete": "list",
|
|
4626
|
+
"aria-expanded": menuOpen,
|
|
4627
|
+
"aria-controls": listId,
|
|
4628
|
+
"aria-activedescendant": menuOpen && visibleItems.length > 0 ? optionId(activeIndex) : void 0
|
|
4629
|
+
} : {},
|
|
4630
|
+
className: cn(
|
|
4631
|
+
composerFieldClass,
|
|
4632
|
+
"absolute inset-0 h-full overflow-y-auto rounded-md focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
4633
|
+
),
|
|
4634
|
+
style: { lineHeight: FIELD_LINE_HEIGHT, maxHeight: fieldHeightFor(maxLines) },
|
|
4635
|
+
onChange: handleChange,
|
|
4636
|
+
onSelect: handleSelect,
|
|
4637
|
+
onKeyDown: handleKeyDown,
|
|
4638
|
+
onCompositionStart: handleCompositionStart,
|
|
4639
|
+
onCompositionEnd: handleCompositionEnd,
|
|
4640
|
+
onCopy: handleCopy,
|
|
4641
|
+
onCut: handleCut,
|
|
4642
|
+
onPaste: handlePaste,
|
|
4643
|
+
onBlur: handleBlur,
|
|
4644
|
+
onScroll: handleScroll
|
|
4645
|
+
}
|
|
4646
|
+
)
|
|
4647
|
+
] }),
|
|
4648
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 px-2 pb-2", children: [
|
|
4649
|
+
leading,
|
|
4650
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
4651
|
+
state.counter.visible && state.counter.remaining !== null && /* @__PURE__ */ jsx(
|
|
4652
|
+
"div",
|
|
4653
|
+
{
|
|
4654
|
+
"aria-live": state.counter.overLimit ? "polite" : void 0,
|
|
4655
|
+
className: cn(
|
|
4656
|
+
composerCounterVariants({
|
|
4657
|
+
overLimit: state.counter.overLimit ? "true" : "false"
|
|
4658
|
+
}),
|
|
4659
|
+
"me-2"
|
|
4660
|
+
),
|
|
4661
|
+
children: strings.counterLabel(state.counter.remaining)
|
|
4662
|
+
}
|
|
4663
|
+
),
|
|
4664
|
+
trailing,
|
|
4665
|
+
primaryAction ? primaryAction(primaryContext) : defaultPrimaryAction
|
|
4666
|
+
] })
|
|
4667
|
+
]
|
|
4668
|
+
}
|
|
4669
|
+
),
|
|
4670
|
+
/* @__PURE__ */ jsx("div", { "aria-live": "polite", className: "sr-only", children: menuOpen && !state.suggestion.loading && state.suggestion.error === null ? visibleItems.length === 0 ? strings.noMatchesLabel(state.activeTrigger?.query ?? "") : strings.resultsAnnouncement(visibleItems.length) : "" })
|
|
4671
|
+
]
|
|
4672
|
+
}
|
|
4673
|
+
);
|
|
4674
|
+
}
|
|
4675
|
+
);
|
|
4676
|
+
RefractionComposer.displayName = "RefractionComposer";
|
|
2694
4677
|
|
|
2695
4678
|
// ../conversation/dist/index.js
|
|
2696
4679
|
function byTime(a, b) {
|
|
@@ -3434,11 +5417,11 @@ var IconListOl = () => svg([
|
|
|
3434
5417
|
h("path", { key: "e", d: "M4 10h2" }),
|
|
3435
5418
|
h("path", { key: "f", d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1" })
|
|
3436
5419
|
]);
|
|
3437
|
-
var
|
|
5420
|
+
var IconArrowUp2 = () => svg([
|
|
3438
5421
|
h("path", { key: "a", d: "M12 19V5" }),
|
|
3439
5422
|
h("path", { key: "b", d: "m5 12 7-7 7 7" })
|
|
3440
5423
|
]);
|
|
3441
|
-
var
|
|
5424
|
+
var IconStop2 = () => svg(h("rect", { x: 7, y: 7, width: 10, height: 10, rx: 1.5 }));
|
|
3442
5425
|
var EMOJI = {
|
|
3443
5426
|
smile: "\u{1F604}",
|
|
3444
5427
|
grin: "\u{1F601}",
|
|
@@ -3482,13 +5465,18 @@ var EMOJI = {
|
|
|
3482
5465
|
moon: "\u{1F319}",
|
|
3483
5466
|
zap: "\u26A1"
|
|
3484
5467
|
};
|
|
5468
|
+
var TRIGGER_CHARS = ["/", "@", ":"];
|
|
5469
|
+
var TRIGGER_QUERY_PATTERN = /^[\w+-]*$/;
|
|
3485
5470
|
function detectTrigger(text, caret) {
|
|
3486
|
-
|
|
3487
|
-
const
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
5471
|
+
let best = null;
|
|
5472
|
+
for (const type of TRIGGER_CHARS) {
|
|
5473
|
+
const hit = detectTriggerInText(text, caret, type);
|
|
5474
|
+
if (!hit || !TRIGGER_QUERY_PATTERN.test(hit.query)) continue;
|
|
5475
|
+
if (!best || hit.start > best.start) {
|
|
5476
|
+
best = { type, query: hit.query, start: hit.start, end: caret };
|
|
5477
|
+
}
|
|
5478
|
+
}
|
|
5479
|
+
return best;
|
|
3492
5480
|
}
|
|
3493
5481
|
function Composer({
|
|
3494
5482
|
placeholder = "Send a message\u2026",
|
|
@@ -3782,7 +5770,7 @@ ${sel}
|
|
|
3782
5770
|
busy ? h(
|
|
3783
5771
|
"button",
|
|
3784
5772
|
{ type: "button", "aria-label": "Stop", className: "flex h-9 w-9 items-center justify-center rounded-full bg-primary text-primary-foreground transition hover:opacity-90", onClick: () => onStop?.() },
|
|
3785
|
-
h(
|
|
5773
|
+
h(IconStop2)
|
|
3786
5774
|
) : h(
|
|
3787
5775
|
"button",
|
|
3788
5776
|
{
|
|
@@ -3792,7 +5780,7 @@ ${sel}
|
|
|
3792
5780
|
disabled: !value.trim() && pending.length === 0,
|
|
3793
5781
|
onClick: submit
|
|
3794
5782
|
},
|
|
3795
|
-
h(
|
|
5783
|
+
h(IconArrowUp2)
|
|
3796
5784
|
)
|
|
3797
5785
|
)
|
|
3798
5786
|
)
|
|
@@ -12109,214 +14097,8 @@ var Checkbox = React11.forwardRef(
|
|
|
12109
14097
|
Checkbox.displayName = "Checkbox";
|
|
12110
14098
|
|
|
12111
14099
|
// ../date-picker/dist/index.js
|
|
12112
|
-
function isSameDay2(a, b) {
|
|
12113
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
12114
|
-
}
|
|
12115
|
-
function startOfMonth2(date) {
|
|
12116
|
-
return new Date(date.getFullYear(), date.getMonth(), 1);
|
|
12117
|
-
}
|
|
12118
|
-
function startOfDay(date) {
|
|
12119
|
-
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
12120
|
-
}
|
|
12121
|
-
function endOfDay(date) {
|
|
12122
|
-
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
|
|
12123
|
-
}
|
|
12124
|
-
var DAY_NAMES2 = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
12125
|
-
function padZero(n) {
|
|
12126
|
-
return n < 10 ? `0${n}` : `${n}`;
|
|
12127
|
-
}
|
|
12128
|
-
function formatDate(date, format, showTime) {
|
|
12129
|
-
if (!date) return "";
|
|
12130
|
-
const year = date.getFullYear();
|
|
12131
|
-
const month = padZero(date.getMonth() + 1);
|
|
12132
|
-
const day = padZero(date.getDate());
|
|
12133
|
-
const hours = padZero(date.getHours());
|
|
12134
|
-
const minutes = padZero(date.getMinutes());
|
|
12135
|
-
let result = format.replace("YYYY", String(year)).replace("MM", month).replace("DD", day);
|
|
12136
|
-
if (showTime) {
|
|
12137
|
-
result = result.replace("HH", hours).replace("mm", minutes);
|
|
12138
|
-
}
|
|
12139
|
-
return result;
|
|
12140
|
-
}
|
|
12141
|
-
function createDatePicker(props = {}) {
|
|
12142
|
-
const {
|
|
12143
|
-
value,
|
|
12144
|
-
onChange,
|
|
12145
|
-
minDate,
|
|
12146
|
-
maxDate,
|
|
12147
|
-
showTime = false,
|
|
12148
|
-
format = showTime ? "YYYY-MM-DD HH:mm" : "YYYY-MM-DD",
|
|
12149
|
-
placeholder = "Select date...",
|
|
12150
|
-
open: controlledOpen,
|
|
12151
|
-
defaultOpen = false,
|
|
12152
|
-
onOpenChange
|
|
12153
|
-
} = props;
|
|
12154
|
-
const today = /* @__PURE__ */ new Date();
|
|
12155
|
-
let internalOpen = controlledOpen ?? defaultOpen;
|
|
12156
|
-
let currentMonth = value ? startOfMonth2(value) : startOfMonth2(today);
|
|
12157
|
-
let view = "calendar";
|
|
12158
|
-
const hours = value ? value.getHours() : 0;
|
|
12159
|
-
const minutes = value ? value.getMinutes() : 0;
|
|
12160
|
-
const triggerId = generateId("rfr-datepicker-trigger");
|
|
12161
|
-
const dropdownId = generateId("rfr-datepicker-dropdown");
|
|
12162
|
-
const gridId = generateId("rfr-datepicker-grid");
|
|
12163
|
-
const labelId = generateId("rfr-datepicker-label");
|
|
12164
|
-
function isOpen() {
|
|
12165
|
-
if (controlledOpen !== void 0) return controlledOpen;
|
|
12166
|
-
return internalOpen;
|
|
12167
|
-
}
|
|
12168
|
-
function isDateDisabled(date) {
|
|
12169
|
-
if (minDate && date < startOfDay(minDate)) return true;
|
|
12170
|
-
if (maxDate && date > endOfDay(maxDate)) return true;
|
|
12171
|
-
return false;
|
|
12172
|
-
}
|
|
12173
|
-
function buildDays() {
|
|
12174
|
-
const year = currentMonth.getFullYear();
|
|
12175
|
-
const month = currentMonth.getMonth();
|
|
12176
|
-
const first = new Date(year, month, 1);
|
|
12177
|
-
const startDow = first.getDay();
|
|
12178
|
-
const gridStart = new Date(year, month, 1 - startDow);
|
|
12179
|
-
const days = [];
|
|
12180
|
-
for (let i = 0; i < 42; i++) {
|
|
12181
|
-
const date = new Date(
|
|
12182
|
-
gridStart.getFullYear(),
|
|
12183
|
-
gridStart.getMonth(),
|
|
12184
|
-
gridStart.getDate() + i
|
|
12185
|
-
);
|
|
12186
|
-
days.push({
|
|
12187
|
-
date,
|
|
12188
|
-
isToday: isSameDay2(date, today),
|
|
12189
|
-
isSelected: value ? isSameDay2(date, value) : false,
|
|
12190
|
-
isCurrentMonth: date.getMonth() === month,
|
|
12191
|
-
isDisabled: isDateDisabled(date)
|
|
12192
|
-
});
|
|
12193
|
-
}
|
|
12194
|
-
return days;
|
|
12195
|
-
}
|
|
12196
|
-
function openPicker() {
|
|
12197
|
-
internalOpen = true;
|
|
12198
|
-
onOpenChange?.(true);
|
|
12199
|
-
}
|
|
12200
|
-
function closePicker() {
|
|
12201
|
-
internalOpen = false;
|
|
12202
|
-
onOpenChange?.(false);
|
|
12203
|
-
}
|
|
12204
|
-
function togglePicker() {
|
|
12205
|
-
if (isOpen()) {
|
|
12206
|
-
closePicker();
|
|
12207
|
-
} else {
|
|
12208
|
-
openPicker();
|
|
12209
|
-
}
|
|
12210
|
-
}
|
|
12211
|
-
function selectDate(date) {
|
|
12212
|
-
if (isDateDisabled(date)) return;
|
|
12213
|
-
const newDate = new Date(date);
|
|
12214
|
-
if (value) {
|
|
12215
|
-
newDate.setHours(value.getHours());
|
|
12216
|
-
newDate.setMinutes(value.getMinutes());
|
|
12217
|
-
}
|
|
12218
|
-
onChange?.(newDate);
|
|
12219
|
-
if (!showTime) {
|
|
12220
|
-
closePicker();
|
|
12221
|
-
}
|
|
12222
|
-
}
|
|
12223
|
-
function setHours(h4) {
|
|
12224
|
-
if (h4 < 0 || h4 > 23) return;
|
|
12225
|
-
const newDate = value ? new Date(value) : /* @__PURE__ */ new Date();
|
|
12226
|
-
newDate.setHours(h4);
|
|
12227
|
-
onChange?.(newDate);
|
|
12228
|
-
}
|
|
12229
|
-
function setMinutes(m) {
|
|
12230
|
-
if (m < 0 || m > 59) return;
|
|
12231
|
-
const newDate = value ? new Date(value) : /* @__PURE__ */ new Date();
|
|
12232
|
-
newDate.setMinutes(m);
|
|
12233
|
-
onChange?.(newDate);
|
|
12234
|
-
}
|
|
12235
|
-
function prevMonth() {
|
|
12236
|
-
currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1);
|
|
12237
|
-
}
|
|
12238
|
-
function nextMonth() {
|
|
12239
|
-
currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1);
|
|
12240
|
-
}
|
|
12241
|
-
function setView(v) {
|
|
12242
|
-
view = v;
|
|
12243
|
-
}
|
|
12244
|
-
function formatDisplay() {
|
|
12245
|
-
return value ? formatDate(value, format, showTime) : placeholder;
|
|
12246
|
-
}
|
|
12247
|
-
const keyboardHandlers = {
|
|
12248
|
-
[Keys.Escape]: (e) => {
|
|
12249
|
-
e.preventDefault();
|
|
12250
|
-
closePicker();
|
|
12251
|
-
}
|
|
12252
|
-
};
|
|
12253
|
-
const triggerProps = {
|
|
12254
|
-
"aria-expanded": isOpen(),
|
|
12255
|
-
"aria-controls": dropdownId,
|
|
12256
|
-
"aria-haspopup": "dialog",
|
|
12257
|
-
id: triggerId,
|
|
12258
|
-
role: "combobox"
|
|
12259
|
-
};
|
|
12260
|
-
const dropdownProps = {
|
|
12261
|
-
role: "dialog",
|
|
12262
|
-
"aria-modal": true,
|
|
12263
|
-
"aria-labelledby": labelId,
|
|
12264
|
-
id: dropdownId
|
|
12265
|
-
};
|
|
12266
|
-
const gridProps = {
|
|
12267
|
-
role: "grid",
|
|
12268
|
-
"aria-labelledby": labelId,
|
|
12269
|
-
id: gridId
|
|
12270
|
-
};
|
|
12271
|
-
function getDayAriaProps(day) {
|
|
12272
|
-
return {
|
|
12273
|
-
role: "gridcell",
|
|
12274
|
-
"aria-selected": day.isSelected,
|
|
12275
|
-
"aria-disabled": day.isDisabled,
|
|
12276
|
-
"aria-current": day.isToday ? "date" : void 0,
|
|
12277
|
-
"aria-label": `${DAY_NAMES2[day.date.getDay()]}, ${day.date.toLocaleDateString("en-US", {
|
|
12278
|
-
month: "long",
|
|
12279
|
-
day: "numeric",
|
|
12280
|
-
year: "numeric"
|
|
12281
|
-
})}`
|
|
12282
|
-
};
|
|
12283
|
-
}
|
|
12284
|
-
return {
|
|
12285
|
-
state: {
|
|
12286
|
-
open: isOpen(),
|
|
12287
|
-
selectedDate: value,
|
|
12288
|
-
view,
|
|
12289
|
-
hours,
|
|
12290
|
-
minutes,
|
|
12291
|
-
currentMonth
|
|
12292
|
-
},
|
|
12293
|
-
days: buildDays(),
|
|
12294
|
-
openPicker,
|
|
12295
|
-
closePicker,
|
|
12296
|
-
togglePicker,
|
|
12297
|
-
selectDate,
|
|
12298
|
-
setHours,
|
|
12299
|
-
setMinutes,
|
|
12300
|
-
prevMonth,
|
|
12301
|
-
nextMonth,
|
|
12302
|
-
setView,
|
|
12303
|
-
formatDisplay,
|
|
12304
|
-
triggerProps,
|
|
12305
|
-
dropdownProps,
|
|
12306
|
-
gridProps,
|
|
12307
|
-
getDayAriaProps,
|
|
12308
|
-
keyboardHandlers,
|
|
12309
|
-
ids: {
|
|
12310
|
-
trigger: triggerId,
|
|
12311
|
-
dropdown: dropdownId,
|
|
12312
|
-
grid: gridId,
|
|
12313
|
-
label: labelId
|
|
12314
|
-
}
|
|
12315
|
-
};
|
|
12316
|
-
}
|
|
12317
14100
|
var datePickerTriggerStyles = "inline-flex items-center gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring cursor-pointer";
|
|
12318
|
-
|
|
12319
|
-
var datePickerDayVariants = cva({
|
|
14101
|
+
cva({
|
|
12320
14102
|
base: "inline-flex h-8 w-8 items-center justify-center rounded-md text-sm cursor-pointer hover:bg-accent hover:text-accent-foreground",
|
|
12321
14103
|
variants: {
|
|
12322
14104
|
state: {
|
|
@@ -12331,205 +14113,38 @@ var datePickerDayVariants = cva({
|
|
|
12331
14113
|
state: "default"
|
|
12332
14114
|
}
|
|
12333
14115
|
});
|
|
12334
|
-
var
|
|
12335
|
-
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
12346
|
-
|
|
12347
|
-
disabled = false
|
|
12348
|
-
}) {
|
|
12349
|
-
const [open, setOpen] = React11.useState(false);
|
|
12350
|
-
const [currentMonth, setCurrentMonth] = React11.useState(
|
|
12351
|
-
() => value ? new Date(value.getFullYear(), value.getMonth(), 1) : new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), 1)
|
|
12352
|
-
);
|
|
12353
|
-
const [view, setView] = React11.useState("calendar");
|
|
12354
|
-
const containerRef = React11.useRef(null);
|
|
12355
|
-
const api = React11.useMemo(
|
|
12356
|
-
() => createDatePicker({
|
|
12357
|
-
value,
|
|
12358
|
-
onChange,
|
|
12359
|
-
minDate,
|
|
12360
|
-
maxDate,
|
|
12361
|
-
showTime,
|
|
12362
|
-
format,
|
|
12363
|
-
placeholder,
|
|
12364
|
-
open,
|
|
12365
|
-
onOpenChange: setOpen
|
|
12366
|
-
}),
|
|
12367
|
-
[value, onChange, minDate, maxDate, showTime, format, placeholder, open]
|
|
12368
|
-
);
|
|
12369
|
-
React11.useMemo(() => {
|
|
12370
|
-
createDatePicker({
|
|
12371
|
-
value,
|
|
12372
|
-
minDate,
|
|
12373
|
-
maxDate,
|
|
12374
|
-
open: true
|
|
12375
|
-
});
|
|
12376
|
-
const tempApi = createDatePicker({
|
|
12377
|
-
value,
|
|
12378
|
-
minDate,
|
|
12379
|
-
maxDate,
|
|
12380
|
-
open: true
|
|
12381
|
-
});
|
|
12382
|
-
return tempApi.days;
|
|
12383
|
-
}, [value, minDate, maxDate, currentMonth]);
|
|
12384
|
-
React11.useEffect(() => {
|
|
12385
|
-
if (!open) return;
|
|
12386
|
-
function handleClick(e) {
|
|
12387
|
-
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
12388
|
-
setOpen(false);
|
|
12389
|
-
}
|
|
12390
|
-
}
|
|
12391
|
-
document.addEventListener("mousedown", handleClick);
|
|
12392
|
-
return () => document.removeEventListener("mousedown", handleClick);
|
|
12393
|
-
}, [open]);
|
|
12394
|
-
React11.useEffect(() => {
|
|
12395
|
-
if (!open) return;
|
|
12396
|
-
function handleKeyDown(e) {
|
|
12397
|
-
if (e.key === "Escape") {
|
|
12398
|
-
e.preventDefault();
|
|
12399
|
-
setOpen(false);
|
|
14116
|
+
var DatePicker = React11.forwardRef(
|
|
14117
|
+
({ value, onChange, minDate, maxDate, showTime = false, format, placeholder, className, disabled = false, ...props }, ref) => {
|
|
14118
|
+
const dateToString = (date) => {
|
|
14119
|
+
if (!date) return "";
|
|
14120
|
+
const offset = date.getTimezoneOffset() * 6e4;
|
|
14121
|
+
const localDate = new Date(date.getTime() - offset);
|
|
14122
|
+
const iso = localDate.toISOString();
|
|
14123
|
+
return showTime ? iso.slice(0, 16) : iso.slice(0, 10);
|
|
14124
|
+
};
|
|
14125
|
+
const handleChange = (e) => {
|
|
14126
|
+
if (!onChange) return;
|
|
14127
|
+
if (e.target.value) {
|
|
14128
|
+
onChange(new Date(e.target.value));
|
|
12400
14129
|
}
|
|
12401
|
-
}
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
}, [open]);
|
|
12405
|
-
const displayValue = api.formatDisplay();
|
|
12406
|
-
const handleSelectDate = (date) => {
|
|
12407
|
-
const newDate = new Date(date);
|
|
12408
|
-
if (value) {
|
|
12409
|
-
newDate.setHours(value.getHours());
|
|
12410
|
-
newDate.setMinutes(value.getMinutes());
|
|
12411
|
-
}
|
|
12412
|
-
onChange?.(newDate);
|
|
12413
|
-
if (!showTime) {
|
|
12414
|
-
setOpen(false);
|
|
12415
|
-
}
|
|
12416
|
-
};
|
|
12417
|
-
const handleHoursChange = (e) => {
|
|
12418
|
-
const h4 = parseInt(e.target.value, 10);
|
|
12419
|
-
if (isNaN(h4) || h4 < 0 || h4 > 23) return;
|
|
12420
|
-
const newDate = value ? new Date(value) : /* @__PURE__ */ new Date();
|
|
12421
|
-
newDate.setHours(h4);
|
|
12422
|
-
onChange?.(newDate);
|
|
12423
|
-
};
|
|
12424
|
-
const handleMinutesChange = (e) => {
|
|
12425
|
-
const m = parseInt(e.target.value, 10);
|
|
12426
|
-
if (isNaN(m) || m < 0 || m > 59) return;
|
|
12427
|
-
const newDate = value ? new Date(value) : /* @__PURE__ */ new Date();
|
|
12428
|
-
newDate.setMinutes(m);
|
|
12429
|
-
onChange?.(newDate);
|
|
12430
|
-
};
|
|
12431
|
-
const monthLabel = currentMonth.toLocaleDateString("en-US", { month: "long", year: "numeric" });
|
|
12432
|
-
return React11.createElement(
|
|
12433
|
-
"div",
|
|
12434
|
-
{ ref: containerRef, className: cn("relative inline-block", className) },
|
|
12435
|
-
React11.createElement(
|
|
12436
|
-
"button",
|
|
12437
|
-
{
|
|
12438
|
-
type: "button",
|
|
12439
|
-
className: cn(datePickerTriggerStyles, disabled && "opacity-50 cursor-not-allowed"),
|
|
12440
|
-
onClick: () => !disabled && setOpen(!open),
|
|
12441
|
-
"aria-expanded": open,
|
|
12442
|
-
"aria-haspopup": "dialog",
|
|
12443
|
-
disabled
|
|
12444
|
-
},
|
|
12445
|
-
displayValue
|
|
12446
|
-
),
|
|
12447
|
-
open && React11.createElement(
|
|
12448
|
-
"div",
|
|
14130
|
+
};
|
|
14131
|
+
return /* @__PURE__ */ jsx(
|
|
14132
|
+
"input",
|
|
12449
14133
|
{
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
"
|
|
12453
|
-
|
|
12454
|
-
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
|
|
12458
|
-
|
|
12459
|
-
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
|
|
12463
|
-
|
|
12464
|
-
},
|
|
12465
|
-
"\u2039"
|
|
12466
|
-
),
|
|
12467
|
-
React11.createElement("span", { className: "text-sm font-medium" }, monthLabel),
|
|
12468
|
-
React11.createElement(
|
|
12469
|
-
"button",
|
|
12470
|
-
{
|
|
12471
|
-
type: "button",
|
|
12472
|
-
className: "p-1 hover:bg-accent rounded cursor-pointer",
|
|
12473
|
-
onClick: () => setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1)),
|
|
12474
|
-
"aria-label": "Next month"
|
|
12475
|
-
},
|
|
12476
|
-
"\u203A"
|
|
12477
|
-
)
|
|
12478
|
-
),
|
|
12479
|
-
React11.createElement(
|
|
12480
|
-
"div",
|
|
12481
|
-
{ className: "grid grid-cols-7 gap-0 text-center", role: "grid" },
|
|
12482
|
-
["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map(
|
|
12483
|
-
(d) => React11.createElement("div", { key: d, className: "text-xs text-muted-foreground py-1 font-medium" }, d)
|
|
12484
|
-
),
|
|
12485
|
-
api.days.map((day, i) => {
|
|
12486
|
-
let state = "default";
|
|
12487
|
-
if (day.isDisabled) state = "disabled";
|
|
12488
|
-
else if (day.isSelected) state = "selected";
|
|
12489
|
-
else if (day.isToday) state = "today";
|
|
12490
|
-
else if (!day.isCurrentMonth) state = "outside";
|
|
12491
|
-
return React11.createElement(
|
|
12492
|
-
"button",
|
|
12493
|
-
{
|
|
12494
|
-
key: i,
|
|
12495
|
-
type: "button",
|
|
12496
|
-
className: datePickerDayVariants({ state }),
|
|
12497
|
-
onClick: () => !day.isDisabled && handleSelectDate(day.date),
|
|
12498
|
-
disabled: day.isDisabled,
|
|
12499
|
-
"aria-selected": day.isSelected,
|
|
12500
|
-
"aria-disabled": day.isDisabled
|
|
12501
|
-
},
|
|
12502
|
-
day.date.getDate()
|
|
12503
|
-
);
|
|
12504
|
-
})
|
|
12505
|
-
),
|
|
12506
|
-
showTime && React11.createElement(
|
|
12507
|
-
"div",
|
|
12508
|
-
{ className: datePickerTimeStyles },
|
|
12509
|
-
React11.createElement("span", { className: "text-sm text-muted-foreground" }, "Time:"),
|
|
12510
|
-
React11.createElement("input", {
|
|
12511
|
-
type: "number",
|
|
12512
|
-
min: 0,
|
|
12513
|
-
max: 23,
|
|
12514
|
-
value: value ? value.getHours() : 0,
|
|
12515
|
-
onChange: handleHoursChange,
|
|
12516
|
-
className: datePickerTimeInputStyles,
|
|
12517
|
-
"aria-label": "Hours"
|
|
12518
|
-
}),
|
|
12519
|
-
React11.createElement("span", { className: "text-muted-foreground" }, ":"),
|
|
12520
|
-
React11.createElement("input", {
|
|
12521
|
-
type: "number",
|
|
12522
|
-
min: 0,
|
|
12523
|
-
max: 59,
|
|
12524
|
-
value: value ? value.getMinutes() : 0,
|
|
12525
|
-
onChange: handleMinutesChange,
|
|
12526
|
-
className: datePickerTimeInputStyles,
|
|
12527
|
-
"aria-label": "Minutes"
|
|
12528
|
-
})
|
|
12529
|
-
)
|
|
12530
|
-
)
|
|
12531
|
-
);
|
|
12532
|
-
}
|
|
14134
|
+
ref,
|
|
14135
|
+
type: showTime ? "datetime-local" : "date",
|
|
14136
|
+
className: cn(datePickerTriggerStyles, "justify-start text-left font-normal w-[280px]", className),
|
|
14137
|
+
value: dateToString(value),
|
|
14138
|
+
min: dateToString(minDate),
|
|
14139
|
+
max: dateToString(maxDate),
|
|
14140
|
+
onChange: handleChange,
|
|
14141
|
+
disabled,
|
|
14142
|
+
placeholder,
|
|
14143
|
+
...props
|
|
14144
|
+
}
|
|
14145
|
+
);
|
|
14146
|
+
}
|
|
14147
|
+
);
|
|
12533
14148
|
DatePicker.displayName = "DatePicker";
|
|
12534
14149
|
|
|
12535
14150
|
// ../emoji-picker/dist/index.js
|
|
@@ -22790,6 +24405,6 @@ var SlotPicker = React11.forwardRef(
|
|
|
22790
24405
|
);
|
|
22791
24406
|
SlotPicker.displayName = "SlotPicker";
|
|
22792
24407
|
|
|
22793
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AltHintState, AnalyticsProvider, AnimatedText, AppShell, AudienceFeatureCard, AudioRoom, AuthGuard, AuthProvider, Avatar2 as Avatar, AvatarFallback, AvatarGroup, AvatarImage, Badge, BadgeDisplay, BottomNav, BrandNetworkCell, Breadcrumbs, BrowserChromeMock, Button, CATEGORY_LABELS, CURSOR_COLORS, Calendar, CalendarHeader, CallControlButton, CallControls, Callout, CalloutContent, CalloutDescription, CalloutIcon, CalloutTitle, Card, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselTrigger, Chat, Checkbox, Checklist, CodeBlock, CodeBlockContent, CodeBlockHeader, CodeEditor, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, ComboboxTrigger, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, Composer, ConfirmationCard, ContentProtection, CookieConsent, Cursor, DEFAULT_CATEGORIES, DEFAULT_VOICE_PILL_POSITION, DEFAULT_VOICE_PILL_SPEAKER, DEFAULT_WAVEFORM_BAR_COUNT, DEFAULT_WAVEFORM_COLOR, DEFAULT_WAVEFORM_HEIGHT, DEFAULT_WAVEFORM_INTENSITY, DEFAULT_WAVEFORM_SMOOTHING, DataTable, DatePicker, DeviceFrame, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, EMOJI_CATEGORIES, EMOJI_DATA, EditorStatusBar, EditorTabs, EmojiPicker, EmptyState, FeedbackButton, FeedbackDialog, FileTree, FileUpload, FloatingReactions, FlowEditor, Footer, GraphView, IconSystem, InfiniteCanvas, InlineEditor, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InstallPrompt, KanbanBoard, KanbanCard, KanbanColumn, KeyboardShortcut, LanguageSelector, LinkCard, LiveCaptions, LiveCursors, LiveTranscript, MarkdownRenderer, MarqueeStrip, Mascot, MasteryBar, MiniMap, MobileNav, MobileNavContent, MobileNavLink, MobileNavTrigger, Navbar, NumberedSteps, OtpInput, STATUS_COLORS as PRESENCE_STATUS_COLORS, STATUS_LABELS as PRESENCE_STATUS_LABELS, Pagination, PasswordInput, Payment, Popover, PopoverClose, PopoverContent, PopoverTrigger, PreCallLobby, PresenceIndicator, PricingCard, ProgressBar, RadialGauge, RadioGroup, RadioItem, RatingScale, ReactionBar, ReactionBurst, ResizableDivider, ResizableLayout, ResizablePane, SANE_DEFAULTS, STATUS_INDICATOR_COLORS as STATUS_COLORS, STATUS_INDICATOR_LABELS as STATUS_LABELS, STICKY_NOTE_COLORS, SearchBar, SearchResultItem, SearchResults, SectionHead, SegmentedControl, SegmentedControlItem, Select, SelectContent, SelectItem, SelectTrigger, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetTitle, SheetTrigger, ShortcutBadge, ShortcutContext, ShortcutHint, ShortcutProvider, ShortcutRegistry, Sidebar, Skeleton, SkeletonText, SkipToContent, SlideViewer, Slider, SlotPicker, SocialAuthButton, SocialAuthRow, SortableList, SpeakingOrb, StatGrid, StatsGrid, StatusIndicator, Step, StepContent, StepDescription, StepIndicator, StepTitle, Steps, StickyNote, Switch, TableOfContents, Tabs, TabsContent, TabsList, TabsTrigger, TelemetryErrorBoundary, TelemetryProvider, Terminal, TestResults, Textarea, ThreadView, Timeline, TimelineItem, Toast, ToastProvider, Toaster, Tooltip, TooltipContent, TooltipTrigger, TypewriterText, VersionSelector, VideoGrid, VideoPlayer, VideoTile, VoicePill, Waveform, Wizard, altHintState, animatedTextVariants, assignCursorColor, avatarFallbackVariants, avatarImageVariants, avatarTokens, avatarVariants, badgeGridVariants, badgeItemVariants, badgeVariants, bottomNavTabVariants, bottomNavVariants, breadcrumbItemVariants, breadcrumbSeparatorStyles, breadcrumbsVariants, buttonTokens, buttonVariants, calendarVariants, canAccessAdmin, canAccessReviewer, cardContentVariants, cardDescriptionVariants, cardFooterVariants, cardHeaderVariants, cardTitleVariants, cardTokens, cardVariants, cellVariants, checkIconPath, checkboxTokens, checkboxVariants, clampVoicePillIntensity, codeEditorTokens, codeEditorVariants, collapsibleContentVariants, comboboxContentVariants, comboboxEmptyVariants, comboboxInputVariants, comboboxItemVariants, comboboxListVariants, comboboxTriggerVariants, commandGroupVariants, commandInputVariants, commandItemVariants, commandVariants, contentProtectionVariants, controlsVariants, createAnalytics, createAppInsightsSink, createConsoleSink, createConversation, createCookieConsent, createGA4ClientSdkSink, createGA4HttpSink, createGA4Sink, createIntensitySamples, createPostHogClientSdkSink, createPostHogHttpSink, createPostHogSink, createPreCallLobby, createSegmentedControl, createSilentSamples, createTelemetry, createVoicePill, createWaveform, dayVariants, deviceFrameVariants, dialogContentVariants, drawWaveform, editorVariants, emojiPickerContainerStyles, emojiPickerEmojiButtonStyles, emojiPickerGridStyles, feedbackDialogVariants, fileUploadDropZoneVariants, fileUploadFileItemStyles, fileUploadFileListStyles, findMessage, footerVariants, formatFileSize, formatRelativeTime, formatShortcut, formatTimestamp, getAssignableRoles, getDefaultPortal, getInitials, getNextSegmentIndex, getReplyCount, getVoicePillAriaLabel, getVoicePillInitials, getVoicePillPosition, getVoicePillPulseStyle, getVoicePillSpeakerKey, getVoicePillSpeakerLabel, getWaveformPeak, globalShortcutRegistry, hasAllRoles, hasAnyRole, hasRole, headerVariants, indeterminateIconPath, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupTokens, inputGroupVariants, inputVariants, installPromptVariants, isWaveformSampleInput, latestBadgeVariants, markdownRendererTokens, menuContentVariants, menuItemVariants, micLevelToBars, mobileNavContentVariants, mobileNavLinkVariants, mobileNavTokens, mobileNavTriggerVariants, mobileNavVariants, navLinkVariants, navbarVariants, nextStickyColor, normalizeBarCount, normalizeIntensity, normalizeSmoothing, normalizeWaveformConfig, normalizeWaveformSamples, optionVariants, otpInputContainerVariants, otpInputSlotVariants, otpInputTokens, overlayStyles, overlayVariants, playerVariants, popoverContentVariants, prepareWaveformCanvas, previewVariants, progressBarVariants, proseVariants, radioCircleVariants, radioGroupVariants, radioItemVariants, reactionAddButtonStyles, reactionBarStyles, reactionCountStyles, reactionEmojiStyles, reactionPillVariants, resampleWaveformSamples, resizableDividerVariants, resizableLayoutTokens, resizableLayoutVariants, resizablePaneVariants, rootIdOf, rowVariants, scaleWaveformSamples, searchBarVariants, searchResultVariants, segmentedControlItemVariants, segmentedControlVariants, selectContentVariants, selectItemVariants, selectMainTimeline, selectReplies, selectRoots, selectThreadMessages, selectTimelineFromState, selectTokens, selectTriggerVariants, selectorVariants, sheetContentVariants, sheetOverlayStyles, shortcutBadgeStyles, shortcutKeyStyles, shortcutSeparatorStyles, sidebarItemVariants, sidebarVariants, skeletonVariants, slideTypeBadgeVariants, slideViewerProgressBarVariants, slideViewerTokens, slideViewerVariants, smoothWaveformSamples, startSessionReplay, statCardVariants, statColumns, statsGridVariants, statusContainerStyles, statusDotVariants, statusLabelStyles, statusPulseVariants, switchThumbVariants, switchTokens, switchVariants, tableVariants, tabsListVariants, tabsTriggerVariants, textareaVariants, threadAuthorStyles, threadAvatarStyles, threadBodyStyles, threadContainerStyles, threadContentStyles, threadMessageStyles, threadReactionsStyles, threadTimestampStyles, toCssDimension, toastVariants, toolbarVariants, tooltipContentVariants, typewriterVariants, useAnalytics, useAuth, useConversation, useCookieConsent, useFloatingReactions, useLogger, useShortcut, useSpan, useTelemetry, useToast, useTrackEvent, useWizard, versionSelectorOptionVariants, versionSelectorVariants, voicePillAvatarStyles, voicePillAvatarWrapStyles, voicePillLabelStyles, voicePillMuteButtonStyles, voicePillPositionVariants, voicePillPulseRingStyles, voicePillRootStyles, voicePillSpeakerStyles, voicePillSubStyles, voicePillTextStyles, voicePillTokens, watermarkVariants, waveformCanvasVariants, waveformVariants };
|
|
24408
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AltHintState, AnalyticsProvider, AnimatedText, AppShell, AudienceFeatureCard, AudioRoom, AuthGuard, AuthProvider, Avatar2 as Avatar, AvatarFallback, AvatarGroup, AvatarImage, Badge, BadgeDisplay, BottomNav, BrandNetworkCell, Breadcrumbs, BrowserChromeMock, Button, CATEGORY_LABELS, CURSOR_COLORS, Calendar, CalendarHeader, CallControlButton, CallControls, Callout, CalloutContent, CalloutDescription, CalloutIcon, CalloutTitle, Card, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselTrigger, Chat, Checkbox, Checklist, CodeBlock, CodeBlockContent, CodeBlockHeader, CodeEditor, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, ComboboxTrigger, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, Composer, ConfirmationCard, ContentProtection, CookieConsent, Cursor, DEFAULT_CATEGORIES, DEFAULT_COMPOSER_STRINGS, DEFAULT_VOICE_PILL_POSITION, DEFAULT_VOICE_PILL_SPEAKER, DEFAULT_WAVEFORM_BAR_COUNT, DEFAULT_WAVEFORM_COLOR, DEFAULT_WAVEFORM_HEIGHT, DEFAULT_WAVEFORM_INTENSITY, DEFAULT_WAVEFORM_SMOOTHING, DataTable, DatePicker, DeviceFrame, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, EMOJI_CATEGORIES, EMOJI_DATA, EditorStatusBar, EditorTabs, EmojiPicker, EmptyState, FeedbackButton, FeedbackDialog, FileTree, FileUpload, FloatingReactions, FlowEditor, Footer, GraphView, IconSystem, InfiniteCanvas, InlineEditor, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InstallPrompt, KanbanBoard, KanbanCard, KanbanColumn, KeyboardShortcut, LanguageSelector, LinkCard, LiveCaptions, LiveCursors, LiveTranscript, MarkdownRenderer, MarqueeStrip, Mascot, MasteryBar, MiniMap, MobileNav, MobileNavContent, MobileNavLink, MobileNavTrigger, Navbar, NumberedSteps, OtpInput, STATUS_COLORS as PRESENCE_STATUS_COLORS, STATUS_LABELS as PRESENCE_STATUS_LABELS, Pagination, PasswordInput, Payment, Popover, PopoverClose, PopoverContent, PopoverTrigger, PreCallLobby, PresenceIndicator, PricingCard, ProgressBar, RadialGauge, RadioGroup, RadioItem, RatingScale, ReactionBar, ReactionBurst, RefractionComposer, ResizableDivider, ResizableLayout, ResizablePane, SANE_DEFAULTS, STATUS_INDICATOR_COLORS as STATUS_COLORS, STATUS_INDICATOR_LABELS as STATUS_LABELS, STICKY_NOTE_COLORS, SearchBar, SearchResultItem, SearchResults, SectionHead, SegmentedControl, SegmentedControlItem, Select, SelectContent, SelectItem, SelectTrigger, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetTitle, SheetTrigger, ShortcutBadge, ShortcutContext, ShortcutHint, ShortcutProvider, ShortcutRegistry, Sidebar, Skeleton, SkeletonText, SkipToContent, SlideViewer, Slider, SlotPicker, SocialAuthButton, SocialAuthRow, SortableList, SpeakingOrb, StatGrid, StatsGrid, StatusIndicator, Step, StepContent, StepDescription, StepIndicator, StepTitle, Steps, StickyNote, Switch, TableOfContents, Tabs, TabsContent, TabsList, TabsTrigger, TelemetryErrorBoundary, TelemetryProvider, Terminal, TestResults, Textarea, ThreadView, Timeline, TimelineItem, Toast, ToastProvider, Toaster, Tooltip, TooltipContent, TooltipTrigger, TypewriterText, VersionSelector, VideoGrid, VideoPlayer, VideoTile, VoicePill, Waveform, Wizard, altHintState, animatedTextVariants, assignCursorColor, avatarFallbackVariants, avatarImageVariants, avatarTokens, avatarVariants, badgeGridVariants, badgeItemVariants, badgeVariants, bottomNavTabVariants, bottomNavVariants, breadcrumbItemVariants, breadcrumbSeparatorStyles, breadcrumbsVariants, buttonTokens, buttonVariants, calendarVariants, canAccessAdmin, canAccessReviewer, cardContentVariants, cardDescriptionVariants, cardFooterVariants, cardHeaderVariants, cardTitleVariants, cardTokens, cardVariants, cellVariants, checkIconPath, checkboxTokens, checkboxVariants, clampVoicePillIntensity, codeEditorTokens, codeEditorVariants, collapsibleContentVariants, comboboxContentVariants, comboboxEmptyVariants, comboboxInputVariants, comboboxItemVariants, comboboxListVariants, comboboxTriggerVariants, commandGroupVariants, commandInputVariants, commandItemVariants, commandVariants, composerAttachmentChipVariants, composerCounterVariants, composerFieldClass, composerMenuClass, composerMenuItemVariants, composerPrimaryActionVariants, composerSurfaceVariants, composerTokenPillClass, composerTrayClass, contentProtectionVariants, controlsVariants, createAnalytics, createAppInsightsSink, createComposer, createConsoleSink, createConversation, createCookieConsent, createGA4ClientSdkSink, createGA4HttpSink, createGA4Sink, createIntensitySamples, createPostHogClientSdkSink, createPostHogHttpSink, createPostHogSink, createPreCallLobby, createSegmentedControl, createSilentSamples, createTelemetry, createVoicePill, createWaveform, dayVariants, deviceFrameVariants, dialogContentVariants, drawWaveform, editorVariants, emojiPickerContainerStyles, emojiPickerEmojiButtonStyles, emojiPickerGridStyles, feedbackDialogVariants, fileUploadDropZoneVariants, fileUploadFileItemStyles, fileUploadFileListStyles, findMessage, footerVariants, formatFileSize, formatRelativeTime, formatShortcut, formatTimestamp, getAssignableRoles, getDefaultPortal, getInitials, getNextSegmentIndex, getReplyCount, getVoicePillAriaLabel, getVoicePillInitials, getVoicePillPosition, getVoicePillPulseStyle, getVoicePillSpeakerKey, getVoicePillSpeakerLabel, getWaveformPeak, globalShortcutRegistry, hasAllRoles, hasAnyRole, hasRole, headerVariants, indeterminateIconPath, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupTokens, inputGroupVariants, inputVariants, installPromptVariants, isWaveformSampleInput, latestBadgeVariants, markdownRendererTokens, menuContentVariants, menuItemVariants, micLevelToBars, mobileNavContentVariants, mobileNavLinkVariants, mobileNavTokens, mobileNavTriggerVariants, mobileNavVariants, navLinkVariants, navbarVariants, nextStickyColor, normalizeBarCount, normalizeIntensity, normalizeSmoothing, normalizeWaveformConfig, normalizeWaveformSamples, optionVariants, otpInputContainerVariants, otpInputSlotVariants, otpInputTokens, overlayStyles, overlayVariants, playerVariants, popoverContentVariants, prepareWaveformCanvas, previewVariants, progressBarVariants, proseVariants, radioCircleVariants, radioGroupVariants, radioItemVariants, reactionAddButtonStyles, reactionBarStyles, reactionCountStyles, reactionEmojiStyles, reactionPillVariants, resampleWaveformSamples, resizableDividerVariants, resizableLayoutTokens, resizableLayoutVariants, resizablePaneVariants, rootIdOf, rowVariants, scaleWaveformSamples, searchBarVariants, searchResultVariants, segmentedControlItemVariants, segmentedControlVariants, selectContentVariants, selectItemVariants, selectMainTimeline, selectReplies, selectRoots, selectThreadMessages, selectTimelineFromState, selectTokens, selectTriggerVariants, selectorVariants, sheetContentVariants, sheetOverlayStyles, shortcutBadgeStyles, shortcutKeyStyles, shortcutSeparatorStyles, sidebarItemVariants, sidebarVariants, skeletonVariants, slideTypeBadgeVariants, slideViewerProgressBarVariants, slideViewerTokens, slideViewerVariants, smoothWaveformSamples, startSessionReplay, statCardVariants, statColumns, statsGridVariants, statusContainerStyles, statusDotVariants, statusLabelStyles, statusPulseVariants, switchThumbVariants, switchTokens, switchVariants, tableVariants, tabsListVariants, tabsTriggerVariants, textareaVariants, threadAuthorStyles, threadAvatarStyles, threadBodyStyles, threadContainerStyles, threadContentStyles, threadMessageStyles, threadReactionsStyles, threadTimestampStyles, toCssDimension, toMessageAttachment, toastVariants, toolbarVariants, tooltipContentVariants, typewriterVariants, useAnalytics, useAuth, useComposer, useConversation, useCookieConsent, useFloatingReactions, useLogger, useShortcut, useSpan, useTelemetry, useToast, useTrackEvent, useWizard, versionSelectorOptionVariants, versionSelectorVariants, voicePillAvatarStyles, voicePillAvatarWrapStyles, voicePillLabelStyles, voicePillMuteButtonStyles, voicePillPositionVariants, voicePillPulseRingStyles, voicePillRootStyles, voicePillSpeakerStyles, voicePillSubStyles, voicePillTextStyles, voicePillTokens, watermarkVariants, waveformCanvasVariants, waveformVariants };
|
|
22794
24409
|
//# sourceMappingURL=index.js.map
|
|
22795
24410
|
//# sourceMappingURL=index.js.map
|