@sesionario/blocks 1.20.0 → 1.21.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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import * as React7 from 'react';
3
- import { createContext, useContext, useState, useRef, useEffect, useLayoutEffect, useCallback, useMemo, useId } from 'react';
3
+ import { createContext, useContext, useState, useRef, useId, useEffect, useCallback, useLayoutEffect, useMemo } from 'react';
4
4
  import { ChevronsUpDown, CheckIcon, Smile, SearchIcon, Search, Clock, Flag, Hash, Lightbulb, Trophy, Plane, Apple, Leaf, Hand, Loader2, AlertTriangle, Inbox, X, ChevronLeft, ChevronRight, Monitor, Sun, Moon, Building2, Check, Plus, Languages, BadgeCheck, Settings, User, Activity, LogOut, LogIn, Upload, Move, ZoomOut, ZoomIn, RotateCcw, RotateCw, Grid3X3, RefreshCw, Pencil, Play, AlertCircle, VolumeX, Pause, Volume1, Volume2, PictureInPicture2, Minimize, Maximize, ArrowDownIcon, MessageCircleDashedIcon, MessageCircle, ChevronUp, ChevronDown, XIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';
5
5
  import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
@@ -425,6 +425,348 @@ function ConfirmDestructiveDialog({
425
425
  ] })
426
426
  ] }) });
427
427
  }
428
+
429
+ // src/components/editable/types.ts
430
+ var DEFAULT_EDITABLE_SECTION_LABELS = {
431
+ edit: "Editar",
432
+ save: "Guardar",
433
+ saving: "Guardando\u2026",
434
+ cancel: "Cancelar",
435
+ saved: "Guardado",
436
+ discardTitle: "\xBFDescartar cambios?",
437
+ discardDescription: "Si sales ahora, se perder\xE1n los cambios que no hayas guardado.",
438
+ discardConfirm: "Descartar",
439
+ discardCancel: "Seguir editando"
440
+ };
441
+
442
+ // src/components/editable/useEditableSection.ts
443
+ function focusFirstField(container) {
444
+ if (!container) return;
445
+ const target = container.querySelector(
446
+ "[data-autofocus], input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), [contenteditable='true']"
447
+ );
448
+ target?.focus();
449
+ }
450
+ function useEditableSection({
451
+ onSave,
452
+ onDiscard,
453
+ isDirty = false,
454
+ labelledBy,
455
+ title,
456
+ labels,
457
+ stableHeight = false
458
+ }) {
459
+ const resolvedLabels = {
460
+ ...DEFAULT_EDITABLE_SECTION_LABELS,
461
+ ...labels
462
+ };
463
+ const [mode, setMode] = useState("reading");
464
+ const [status, setStatus] = useState(null);
465
+ const [confirmOpen, setConfirmOpen] = useState(false);
466
+ const [minHeightPx, setMinHeightPx] = useState(void 0);
467
+ const contentRef = useRef(null);
468
+ const editButtonRef = useRef(null);
469
+ const measuredHeightRef = useRef(0);
470
+ const shouldFocusEditRef = useRef(false);
471
+ const shouldFocusFirstFieldRef = useRef(false);
472
+ const editButtonId = useId();
473
+ const contentFormId = useId();
474
+ const isEditing = mode === "editing" || mode === "saving";
475
+ const isSaving = mode === "saving";
476
+ useEffect(() => {
477
+ if (mode === "reading" && shouldFocusEditRef.current) {
478
+ shouldFocusEditRef.current = false;
479
+ editButtonRef.current?.focus();
480
+ return;
481
+ }
482
+ if (mode === "editing" && shouldFocusFirstFieldRef.current) {
483
+ shouldFocusFirstFieldRef.current = false;
484
+ const invalid = contentRef.current?.querySelector(
485
+ "[aria-invalid='true']"
486
+ );
487
+ if (invalid) {
488
+ invalid.focus();
489
+ return;
490
+ }
491
+ focusFirstField(contentRef.current);
492
+ }
493
+ }, [mode]);
494
+ const exitToReading = useCallback(() => {
495
+ setConfirmOpen(false);
496
+ shouldFocusEditRef.current = true;
497
+ setMode("reading");
498
+ onDiscard?.();
499
+ }, [onDiscard]);
500
+ const startEdit = useCallback(() => {
501
+ setStatus(null);
502
+ shouldFocusFirstFieldRef.current = true;
503
+ setMode("editing");
504
+ }, []);
505
+ const requestCancel = useCallback(() => {
506
+ if (isSaving) return;
507
+ if (isDirty) {
508
+ setConfirmOpen(true);
509
+ return;
510
+ }
511
+ exitToReading();
512
+ }, [exitToReading, isDirty, isSaving]);
513
+ const handleSubmit = useCallback(
514
+ (event) => {
515
+ event.preventDefault();
516
+ if (isSaving) return;
517
+ void (async () => {
518
+ setMode("saving");
519
+ setStatus(null);
520
+ try {
521
+ await onSave();
522
+ setStatus(resolvedLabels.saved);
523
+ shouldFocusEditRef.current = true;
524
+ setMode("reading");
525
+ } catch {
526
+ shouldFocusFirstFieldRef.current = true;
527
+ setMode("editing");
528
+ }
529
+ })();
530
+ },
531
+ [isSaving, onSave, resolvedLabels.saved]
532
+ );
533
+ const handleFormKeyDown = useCallback(
534
+ (event) => {
535
+ if (event.key !== "Escape") return;
536
+ event.preventDefault();
537
+ requestCancel();
538
+ },
539
+ [requestCancel]
540
+ );
541
+ useEffect(() => {
542
+ if (!stableHeight || !isEditing) return;
543
+ const el = contentRef.current;
544
+ if (!el) return;
545
+ const measure = () => {
546
+ const height = el.getBoundingClientRect().height;
547
+ if (height > measuredHeightRef.current) {
548
+ measuredHeightRef.current = height;
549
+ setMinHeightPx(height);
550
+ }
551
+ };
552
+ measure();
553
+ const observer = new ResizeObserver(measure);
554
+ observer.observe(el);
555
+ return () => observer.disconnect();
556
+ }, [isEditing, stableHeight]);
557
+ const editButtonNameProps = labelledBy != null ? { "aria-labelledby": `${labelledBy} ${editButtonId}` } : title != null && title.length > 0 ? { "aria-label": `${resolvedLabels.edit} ${title}` } : { "aria-label": resolvedLabels.edit };
558
+ return {
559
+ mode,
560
+ isEditing,
561
+ isSaving,
562
+ startEdit,
563
+ requestCancel,
564
+ formProps: {
565
+ onSubmit: handleSubmit,
566
+ onKeyDown: handleFormKeyDown,
567
+ noValidate: true
568
+ },
569
+ contentRef,
570
+ editButtonRef,
571
+ contentFormId,
572
+ editButtonProps: {
573
+ type: "button",
574
+ id: editButtonId,
575
+ onClick: startEdit,
576
+ ref: editButtonRef,
577
+ ...editButtonNameProps
578
+ },
579
+ saveButtonProps: {
580
+ type: "submit",
581
+ disabled: isSaving
582
+ },
583
+ cancelButtonProps: {
584
+ type: "button",
585
+ onClick: requestCancel,
586
+ disabled: isSaving
587
+ },
588
+ status,
589
+ statusProps: {
590
+ role: "status",
591
+ "aria-live": "polite",
592
+ className: "sr-only"
593
+ },
594
+ confirmDiscard: {
595
+ open: confirmOpen,
596
+ onOpenChange: setConfirmOpen,
597
+ title: resolvedLabels.discardTitle,
598
+ description: resolvedLabels.discardDescription,
599
+ confirmLabel: resolvedLabels.discardConfirm,
600
+ cancelLabel: resolvedLabels.discardCancel,
601
+ onConfirm: exitToReading
602
+ },
603
+ resolvedLabels,
604
+ contentStyle: stableHeight && minHeightPx != null ? { minHeight: minHeightPx } : void 0,
605
+ actionsClassName: "flex min-h-9 min-w-[11rem] flex-wrap items-center justify-end gap-2"
606
+ };
607
+ }
608
+ function EditableSection({
609
+ readView,
610
+ editView,
611
+ children,
612
+ className,
613
+ ...options
614
+ }) {
615
+ const section = useEditableSection(options);
616
+ const {
617
+ isEditing,
618
+ isSaving,
619
+ formProps,
620
+ contentRef,
621
+ contentFormId,
622
+ editButtonProps,
623
+ saveButtonProps,
624
+ cancelButtonProps,
625
+ status,
626
+ statusProps,
627
+ confirmDiscard,
628
+ resolvedLabels,
629
+ contentStyle,
630
+ actionsClassName,
631
+ mode
632
+ } = section;
633
+ const actionButtons = !isEditing ? /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", ...editButtonProps, children: resolvedLabels.edit }) : /* @__PURE__ */ jsxs(Fragment, { children: [
634
+ /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", ...cancelButtonProps, children: resolvedLabels.cancel }),
635
+ /* @__PURE__ */ jsx(
636
+ Button,
637
+ {
638
+ size: "sm",
639
+ type: "submit",
640
+ form: contentFormId,
641
+ disabled: saveButtonProps.disabled,
642
+ children: isSaving ? resolvedLabels.saving : resolvedLabels.save
643
+ }
644
+ )
645
+ ] });
646
+ const actions = /* @__PURE__ */ jsx("div", { "data-slot": "editable-section-actions", className: actionsClassName, children: actionButtons });
647
+ const content = isEditing ? /* @__PURE__ */ jsx(
648
+ "form",
649
+ {
650
+ id: contentFormId,
651
+ ref: contentRef,
652
+ "data-slot": "editable-section-content",
653
+ className: cn("sesionario-editable-section-content space-y-4"),
654
+ style: contentStyle,
655
+ ...formProps,
656
+ children: editView()
657
+ }
658
+ ) : /* @__PURE__ */ jsx(
659
+ "div",
660
+ {
661
+ ref: contentRef,
662
+ "data-slot": "editable-section-content",
663
+ className: "sesionario-editable-section-content",
664
+ style: contentStyle,
665
+ children: readView()
666
+ }
667
+ );
668
+ const statusNode = /* @__PURE__ */ jsx("span", { ...statusProps, "data-slot": "editable-section-status", children: status });
669
+ const dialog = /* @__PURE__ */ jsx(
670
+ ConfirmDestructiveDialog,
671
+ {
672
+ open: confirmDiscard.open,
673
+ onOpenChange: confirmDiscard.onOpenChange,
674
+ title: confirmDiscard.title,
675
+ description: confirmDiscard.description,
676
+ confirmLabel: confirmDiscard.confirmLabel,
677
+ cancelLabel: confirmDiscard.cancelLabel,
678
+ onConfirm: confirmDiscard.onConfirm
679
+ }
680
+ );
681
+ if (children) {
682
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
683
+ children({
684
+ actions,
685
+ content,
686
+ status: statusNode,
687
+ mode,
688
+ isSaving,
689
+ isEditing
690
+ }),
691
+ dialog
692
+ ] });
693
+ }
694
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "editable-section", className: cn("space-y-4", className), children: [
695
+ actions,
696
+ content,
697
+ statusNode,
698
+ dialog
699
+ ] });
700
+ }
701
+ function DataList({ className, ...props }) {
702
+ return /* @__PURE__ */ jsx(
703
+ "dl",
704
+ {
705
+ "data-slot": "data-list",
706
+ className: cn("grid gap-4 sm:grid-cols-2", className),
707
+ ...props
708
+ }
709
+ );
710
+ }
711
+ function DataListItem({
712
+ label,
713
+ children,
714
+ empty = "\u2014",
715
+ className,
716
+ labelClassName,
717
+ valueClassName
718
+ }) {
719
+ const isEmpty = children == null || children === false || typeof children === "string" && children.trim().length === 0;
720
+ return /* @__PURE__ */ jsxs(
721
+ "div",
722
+ {
723
+ "data-slot": "data-list-item",
724
+ className: cn("flex flex-col gap-1.5", className),
725
+ children: [
726
+ /* @__PURE__ */ jsx(
727
+ "dt",
728
+ {
729
+ className: cn(
730
+ "text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
731
+ labelClassName
732
+ ),
733
+ children: label
734
+ }
735
+ ),
736
+ /* @__PURE__ */ jsx(
737
+ "dd",
738
+ {
739
+ className: cn(
740
+ "text-sm wrap-break-word",
741
+ isEmpty && "text-muted-foreground",
742
+ valueClassName
743
+ ),
744
+ children: isEmpty ? empty : children
745
+ }
746
+ )
747
+ ]
748
+ }
749
+ );
750
+ }
751
+ function FieldMessage({
752
+ id,
753
+ children,
754
+ className,
755
+ ...props
756
+ }) {
757
+ const hasMessage = children != null && children !== false && !(typeof children === "string" && children.trim().length === 0);
758
+ return /* @__PURE__ */ jsx(
759
+ "p",
760
+ {
761
+ id,
762
+ role: hasMessage ? "alert" : void 0,
763
+ "data-slot": "field-message",
764
+ className: cn("min-h-5 text-xs text-destructive", className),
765
+ ...props,
766
+ children: hasMessage ? children : "\xA0"
767
+ }
768
+ );
769
+ }
428
770
  var COLLAPSED_MAX_HEIGHT_REM = 11;
429
771
  function ExpandableText({
430
772
  children,
@@ -8289,6 +8631,6 @@ function useRealtimeChannel({
8289
8631
  }, [enabled, reconnectDelayMs]);
8290
8632
  }
8291
8633
 
8292
- export { AvatarEditor, AvatarEditorDialog, Bubble, BubbleContent, BubbleGroup, BubbleReactions, ChatMessageList, ConfirmDestructiveDialog, DropdownMenuItem, DropdownMenuSeparator, EmojiInput, EmojiPicker, EmojiPickerPopover, EmojiTextarea, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, ErrorState, ExpandableText, FeedVideoPlayer, ImageLightbox, LanguageContext, LanguageSwitcher, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageComposer, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, OrgSwitcher, PLATFORM_ACCOUNT_ORG_COLLAPSE_AT, PaymentIcon, PhoneInput, PlatformAccountMenu, PlatformNavbar, SearchCommand, SearchablePicker, SupportMessengerProvider, ThemeSwitcher, VerifiedProfessionalBadge, VideoPlayer, avatarFallbackStyle, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describeAvResync, describePlaybackError, formatPaymentCardBrand, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, mergePlatformAccountOrgs, normalizeEmojiQuery, normalizePaymentCardBrand, paymentIconBrandFromStripe, paymentTypeFromStripeBrand, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useFeedExclusivePlayback, useHlsPlayback, useLanguageContext, useMediaQuery2 as useMediaQuery, usePlaybackStats, useRealtimeChannel, useScrollFadeXEdges, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
8634
+ export { AvatarEditor, AvatarEditorDialog, Bubble, BubbleContent, BubbleGroup, BubbleReactions, ChatMessageList, ConfirmDestructiveDialog, DEFAULT_EDITABLE_SECTION_LABELS, DataList, DataListItem, DropdownMenuItem, DropdownMenuSeparator, EditableSection, EmojiInput, EmojiPicker, EmojiPickerPopover, EmojiTextarea, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, ErrorState, ExpandableText, FeedVideoPlayer, FieldMessage, ImageLightbox, LanguageContext, LanguageSwitcher, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageComposer, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, OrgSwitcher, PLATFORM_ACCOUNT_ORG_COLLAPSE_AT, PaymentIcon, PhoneInput, PlatformAccountMenu, PlatformNavbar, SearchCommand, SearchablePicker, SupportMessengerProvider, ThemeSwitcher, VerifiedProfessionalBadge, VideoPlayer, avatarFallbackStyle, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describeAvResync, describePlaybackError, formatPaymentCardBrand, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, mergePlatformAccountOrgs, normalizeEmojiQuery, normalizePaymentCardBrand, paymentIconBrandFromStripe, paymentTypeFromStripeBrand, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useEditableSection, useFeedExclusivePlayback, useHlsPlayback, useLanguageContext, useMediaQuery2 as useMediaQuery, usePlaybackStats, useRealtimeChannel, useScrollFadeXEdges, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
8293
8635
  //# sourceMappingURL=index.js.map
8294
8636
  //# sourceMappingURL=index.js.map