@refraction-ui/react 0.2.1 → 0.3.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 CHANGED
@@ -128,7 +128,6 @@ __export(index_exports, {
128
128
  Command: () => Command,
129
129
  CommandEmpty: () => CommandEmpty,
130
130
  CommandGroup: () => CommandGroup,
131
- CommandInput: () => CommandInput,
132
131
  CommandItem: () => CommandItem,
133
132
  CommandList: () => CommandList,
134
133
  CommandSeparator: () => CommandSeparator,
@@ -12322,6 +12321,196 @@ var PaymentButton = React41__namespace.forwardRef(
12322
12321
  );
12323
12322
  PaymentButton.displayName = "PaymentButton";
12324
12323
 
12324
+ // ../command-input/dist/index.js
12325
+ var CommandInput2 = class {
12326
+ state = {
12327
+ nodes: [],
12328
+ rawText: "",
12329
+ cursorPosition: 0,
12330
+ activeTrigger: null,
12331
+ activeCommandText: null
12332
+ };
12333
+ options;
12334
+ constructor(options) {
12335
+ this.options = { ...options };
12336
+ }
12337
+ handleInput(text, cursorPosition) {
12338
+ this.state.rawText = text;
12339
+ this.state.cursorPosition = cursorPosition;
12340
+ this.parseInput();
12341
+ this.notifyStateChange();
12342
+ }
12343
+ handleKeyDown(key, event) {
12344
+ if (this.state.activeTrigger) {
12345
+ if (key === "Escape") {
12346
+ if (event) event.preventDefault();
12347
+ this.state.activeTrigger = null;
12348
+ this.state.activeCommandText = null;
12349
+ if (this.options.onCommandCancel) {
12350
+ this.options.onCommandCancel();
12351
+ }
12352
+ this.notifyStateChange();
12353
+ } else if (key === "Enter") {
12354
+ if (event) event.preventDefault();
12355
+ const trigger = this.state.activeTrigger;
12356
+ const text = this.state.activeCommandText || "";
12357
+ this.state.activeTrigger = null;
12358
+ this.state.activeCommandText = null;
12359
+ if (this.options.onCommandCommit) {
12360
+ this.options.onCommandCommit(trigger, text);
12361
+ }
12362
+ this.notifyStateChange();
12363
+ }
12364
+ }
12365
+ }
12366
+ get value() {
12367
+ return this.state.nodes;
12368
+ }
12369
+ getState() {
12370
+ return { ...this.state };
12371
+ }
12372
+ parseInput() {
12373
+ const { rawText, cursorPosition } = this.state;
12374
+ this.state.activeTrigger = null;
12375
+ this.state.activeCommandText = null;
12376
+ for (let i = cursorPosition - 1; i >= 0; i--) {
12377
+ const char = rawText[i];
12378
+ const matchedTrigger = this.options.triggers.find((t) => t.char === char);
12379
+ if (matchedTrigger) {
12380
+ const isStartOfWord = i === 0 || /\\s/.test(rawText[i - 1]);
12381
+ if (isStartOfWord) {
12382
+ const commandText = rawText.slice(i + 1, cursorPosition);
12383
+ if (!/\\s/.test(commandText)) {
12384
+ let isValid = true;
12385
+ if (matchedTrigger.pattern) {
12386
+ isValid = matchedTrigger.pattern.test(commandText);
12387
+ }
12388
+ if (isValid) {
12389
+ this.state.activeTrigger = matchedTrigger;
12390
+ this.state.activeCommandText = commandText;
12391
+ if (this.options.onCommandTriggered) {
12392
+ this.options.onCommandTriggered(matchedTrigger, commandText);
12393
+ }
12394
+ }
12395
+ }
12396
+ }
12397
+ break;
12398
+ }
12399
+ if (/\\s/.test(char)) {
12400
+ break;
12401
+ }
12402
+ }
12403
+ const nodes = [];
12404
+ if (this.options.triggers.length === 0) {
12405
+ nodes.push({ type: "text", text: rawText });
12406
+ this.state.nodes = nodes;
12407
+ return;
12408
+ }
12409
+ const triggerChars = this.options.triggers.map((t) => t.char.replace(/[.*+?^\${}()|[\\]\\\\]/g, "\\\\$&"));
12410
+ const patternStr = `(^|\\\\s)(${triggerChars.join("|")})([^\\\\s]*)`;
12411
+ const regex = new RegExp(patternStr, "g");
12412
+ let currentIndex = 0;
12413
+ let match;
12414
+ while ((match = regex.exec(rawText)) !== null) {
12415
+ const precedingWhitespace = match[1];
12416
+ const triggerChar = match[2];
12417
+ const commandText = match[3];
12418
+ const matchStart = match.index;
12419
+ const triggerStart = matchStart + precedingWhitespace.length;
12420
+ const triggerConfig = this.options.triggers.find((t) => t.char === triggerChar);
12421
+ let isValid = true;
12422
+ if (triggerConfig?.pattern && commandText.length > 0) {
12423
+ isValid = triggerConfig.pattern.test(commandText);
12424
+ }
12425
+ if (isValid) {
12426
+ if (triggerStart > currentIndex) {
12427
+ nodes.push({ type: "text", text: rawText.slice(currentIndex, triggerStart) });
12428
+ }
12429
+ nodes.push({ type: "command", trigger: triggerChar, text: commandText });
12430
+ currentIndex = regex.lastIndex;
12431
+ }
12432
+ }
12433
+ if (currentIndex < rawText.length) {
12434
+ nodes.push({ type: "text", text: rawText.slice(currentIndex) });
12435
+ }
12436
+ this.state.nodes = nodes;
12437
+ }
12438
+ notifyStateChange() {
12439
+ if (this.options.onStateChange) {
12440
+ this.options.onStateChange({ ...this.state });
12441
+ }
12442
+ }
12443
+ };
12444
+ var CommandInput3 = React41.forwardRef(
12445
+ ({
12446
+ value = "",
12447
+ onChange,
12448
+ triggers = [],
12449
+ renderPopover,
12450
+ className,
12451
+ ...props
12452
+ }, ref) => {
12453
+ const localRef = React41.useRef(null);
12454
+ const containerRef = ref || localRef;
12455
+ const [popoverState, setPopoverState] = React41.useState({
12456
+ isOpen: false,
12457
+ trigger: "",
12458
+ search: "",
12459
+ position: { top: 0, left: 0 }
12460
+ });
12461
+ const coreRef = React41.useRef(null);
12462
+ React41.useEffect(() => {
12463
+ if (containerRef.current && !coreRef.current) {
12464
+ coreRef.current = new CommandInput2({
12465
+ triggers,
12466
+ onCommandTriggered: (trigger, search) => {
12467
+ setPopoverState({
12468
+ isOpen: true,
12469
+ trigger: trigger.char,
12470
+ search,
12471
+ position: { top: 0, left: 0 }
12472
+ });
12473
+ },
12474
+ onCommandCancel: () => {
12475
+ setPopoverState((prev) => ({ ...prev, isOpen: false }));
12476
+ },
12477
+ onStateChange: (state) => {
12478
+ onChange?.(state.rawText);
12479
+ }
12480
+ });
12481
+ }
12482
+ }, [triggers, onChange]);
12483
+ React41.useEffect(() => {
12484
+ if (containerRef.current && containerRef.current.innerHTML !== value && coreRef.current) {
12485
+ containerRef.current.innerHTML = value;
12486
+ }
12487
+ }, [value]);
12488
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative w-full", className), children: [
12489
+ /* @__PURE__ */ jsxRuntime.jsx(
12490
+ "div",
12491
+ {
12492
+ ref: containerRef,
12493
+ contentEditable: true,
12494
+ suppressContentEditableWarning: true,
12495
+ className: "w-full min-h-[40px] p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500",
12496
+ onInput: (e) => {
12497
+ coreRef.current?.handleInput(e.currentTarget.textContent || "", 0);
12498
+ },
12499
+ onKeyDown: (e) => {
12500
+ coreRef.current?.handleKeyDown(e.key, e);
12501
+ },
12502
+ ...props
12503
+ }
12504
+ ),
12505
+ renderPopover && renderPopover({
12506
+ ...popoverState,
12507
+ close: () => setPopoverState((prev) => ({ ...prev, isOpen: false }))
12508
+ })
12509
+ ] });
12510
+ }
12511
+ );
12512
+ CommandInput3.displayName = "CommandInput";
12513
+
12325
12514
  exports.Accordion = Accordion;
12326
12515
  exports.AccordionContent = AccordionContent;
12327
12516
  exports.AccordionItem = AccordionItem;
@@ -12363,7 +12552,6 @@ exports.CollapsibleTrigger = CollapsibleTrigger;
12363
12552
  exports.Command = Command;
12364
12553
  exports.CommandEmpty = CommandEmpty;
12365
12554
  exports.CommandGroup = CommandGroup;
12366
- exports.CommandInput = CommandInput;
12367
12555
  exports.CommandItem = CommandItem;
12368
12556
  exports.CommandList = CommandList;
12369
12557
  exports.CommandSeparator = CommandSeparator;