@elaraai/e3-ui-components 1.0.83 → 1.0.84

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
@@ -20,19 +20,19 @@ var __privateWrapper = (obj, member, setter, getter) => ({
20
20
  var _focused, _cleanup, _setup, _a, _provider, _providerCalled, _b, _online, _cleanup2, _setup2, _c, _gcTimeout, _d, _initialState, _revertState, _cache, _client, _retryer, _defaultOptions, _abortSignalConsumed, _Query_instances, isInitialPausedFetch_fn, dispatch_fn, _e, _client2, _observers, _mutationCache, _retryer2, _Mutation_instances, dispatch_fn2, _f, _mutations, _scopes, _mutationId, _g, _queries, _h, _queryCache, _mutationCache2, _defaultOptions2, _queryDefaults, _mutationDefaults, _mountCount, _unsubscribeFocus, _unsubscribeOnline, _i, _j;
21
21
  import { variant, SortedMap, compareFor, EastError, fromEastTypeValue, East, none as none$1, some, OptionType, BooleanType, NullType, ConflictError, equalFor, toEastTypeValue, PatchType, diffFor, applyFor, encodeBeast2For, decodeBeast2For, BlobType, StringType, IntegerType, isTypeValueEqual, StructType, walkPatch, pathToString, pathDisplay, parseFor, printFor, FloatType, equivalentFor, prunePatchFor, detectConflictsFor, mergeWithResolutionsFor, validatePatchFor, canonicalTypeValue, ArrayType, EastTypeValueType, defaultValue, DateTimeType } from "@elaraai/east";
22
22
  import { EastTypeType, formatDateTime, parseDateTimeFormatted, tokenizeDateTimeFormat } from "@elaraai/east/internal";
23
- import { DataBindModeType, DataBindPrimitives, bindPlatformFn, DataPagedPrimitives, bindPagedPlatformFn, bindPagedPinnedPlatformFn, FuncBindPrimitives, FuncErrorType, FuncStatusType, funcBindPlatformFn, RecordBindPrimitives, recordBindPlatformFn, Diff, Ontology, FuncBindHandleType, Experiment, decisionBindPlatformFn, DecisionBindPrimitives, DecisionConstraintType, DiffBindingType, CommitStateType, VerdictType, AnswerType, judgementInputType, DecisionType, DecisionQueue, DecisionJournal } from "@elaraai/e3-ui/internal";
23
+ import { DataBindModeType, DataBindPrimitives, bindPlatformFn, DataPagedPrimitives, bindPagedPlatformFn, bindPagedPinnedPlatformFn, FuncBindPrimitives, FuncErrorType, FuncStatusType, funcBindPlatformFn, RecordBindPrimitives, recordBindPlatformFn, Diff, Ontology, FuncBindHandleType, Experiment, decisionBindPlatformFn, DecisionBindPrimitives, DecisionConstraintType, DiffBindingType, CommitStateType, VerdictType, AnswerType, judgementInputType, DecisionType, DecisionQueue, DecisionJournal, StudioKeyType, StudioPageComponent, saveCells, Studio, nameWriteRefusal, libraryTemplates, libraryPages, libraryProjects, publishRefusal, publishSummary, inspectorSelection, canvasTiles, palettePages, paletteCards, builderKeys, StudioCellType, StudioBuilderComponent, StudioLibraryComponent } from "@elaraai/e3-ui/internal";
24
24
  import { registerReactiveTracker, registerPlatformImplementation, StateRuntime, getRegisteredPlatformImplementations, boundSliceConfig } from "@elaraai/east-ui-components/platform";
25
25
  import { TreePathType, DatasetStatusType, pathToString as pathToString$1 } from "@elaraai/e3-types";
26
26
  import { workspaceStatus, datasetListAt, datasetList, dataflowExecuteLaunch, datasetSet, datasetGet, ApiError, DatasetHashMismatchError, datasetGetStatus, datasetFindKey, datasetGetPage, workspaceFunctionCall, workspaceFunctionList, workspaceRecordHistory, workspaceRecordMutate, workspaceRecordDescribe, repoCreate, repoGc, repoGcStart, repoGcStatus, repoList, repoRemove, repoStatus, packageExport, packageGet, packageImport, packageList, packageRemove, workspaceCreate, workspaceDeploy, workspaceExport, workspaceGet, workspaceList, workspaceRemove, datasetListRecursive, datasetListRecursivePaths, datasetListWithStatus, taskExecutionList, taskGet, taskList, dataflowCancel, dataflowExecute, dataflowExecutePoll, dataflowGraph, taskLogs } from "@elaraai/e3-api-client";
27
27
  import { SeekQueryType, SeekRangeType, slicePredicateMatches, ValueTree } from "@elaraai/east-ui";
28
28
  import { jsx as jsx$1, Fragment, jsxs } from "react/jsx-runtime";
29
29
  import * as React from "react";
30
- import React__default, { useId, useMemo, useContext, createContext, useRef, useState, useEffect, useCallback, useSyncExternalStore, memo, forwardRef, useLayoutEffect, Fragment as Fragment$1, Component } from "react";
31
- import { Box, Flex, Text, HStack, Input, useSlotRecipe, useRecipe, VStack, useToken, Drawer, Portal, Field, NativeSelect, Textarea, chakra, Tooltip, SegmentGroup, Menu, HoverCard, useChakraContext, Spinner, Code, Clipboard, IconButton, Button, Tabs, Badge, useTabs } from "@chakra-ui/react";
32
- import { formatters, useFormatters, useDataStable, implementUIComponent, getSomeorUndefined, formatPredicate, SliceEditPopover, SlicePredicateBuilder, EastChakraSelect, EastChakraStringInput, EastChakraDateTimeInput, EastChakraFloatInput, EastChakraIntegerInput, useSliceReactivity, useContainerBelow, usePersistedState, SliceRailCluster, EastChakraComponent, ClauseChip, StateImpl, NavImpl, SliceImpl, SliceApplyImpl, OverlayImpl, ClipboardImpl, DownloadImpl, ShareImpl, LoadingIcon, DatasetKeySearch, EastChakraValueTree, keyRangePredicates, createUIStore, UIStoreProvider } from "@elaraai/east-ui-components";
30
+ import React__default, { useId, useMemo, useContext, createContext, useRef, useState, useEffect, useCallback, useSyncExternalStore, memo, forwardRef, useLayoutEffect, Fragment as Fragment$1, createElement as createElement$1, Component } from "react";
31
+ import { Box, Flex, Text, HStack, Input, useSlotRecipe, useRecipe, VStack, useToken, Drawer, Portal, Field, NativeSelect, Textarea, chakra, Tooltip, SegmentGroup, Menu, HoverCard, useChakraContext, Spinner, createListCollection, Select, Button, Code, Clipboard, IconButton, Tabs, Badge, useTabs } from "@chakra-ui/react";
32
+ import { formatters, useFormatters, useDataStable, implementUIComponent, getSomeorUndefined, formatPredicate, SliceEditPopover, SlicePredicateBuilder, EastChakraSelect, EastChakraStringInput, EastChakraDateTimeInput, EastChakraFloatInput, EastChakraIntegerInput, useSliceReactivity, useContainerBelow, usePersistedState, SliceRailCluster, EastChakraComponent, ClauseChip, StateRuntime as StateRuntime$1, EmptyStateView, BannerView, SnapGridTiles, useTrackedEvaluation, DockPane, EastChakraLibrary, SnapGridEditor, LibraryLayoutSwitch, Toolbar, StateImpl, NavImpl, SliceImpl, SliceApplyImpl, OverlayImpl, ClipboardImpl, DownloadImpl, ShareImpl, LoadingIcon, DatasetKeySearch, EastChakraValueTree, keyRangePredicates, createUIStore, UIStoreProvider } from "@elaraai/east-ui-components";
33
33
  import { DatasetKeySearch as DatasetKeySearch2 } from "@elaraai/east-ui-components";
34
34
  import { createPortal } from "react-dom";
35
- import { sliceMatches, pruneRetainedPages } from "@elaraai/east-ui/internal";
35
+ import { sliceMatches, EditingDraftFieldType, Editing, pruneRetainedPages } from "@elaraai/east-ui/internal";
36
36
  import { QueryClient as QueryClient$1, QueryClientProvider, useMutation, useQuery, useQueryClient, keepPreviousData } from "@tanstack/react-query";
37
37
  import { useVirtualizer } from "@tanstack/react-virtual";
38
38
  var Subscribable = class {
@@ -4846,7 +4846,7 @@ function createInMemoryFunctionApi(functions2) {
4846
4846
  name: def.name,
4847
4847
  inputTypes: def.inputTypes,
4848
4848
  outputType: def.outputType,
4849
- runner: variant("east_node", { platforms: [] })
4849
+ runner: variant("east_node", { platforms: [], decode: variant("lazy", null) })
4850
4850
  }));
4851
4851
  },
4852
4852
  async call(_workspace, fnName, req) {
@@ -8450,6 +8450,16 @@ var faMinus = {
8450
8450
  iconName: "minus",
8451
8451
  icon: [448, 512, [8211, 8722, 10134, "subtract"], "f068", "M0 256c0-17.7 14.3-32 32-32l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32z"]
8452
8452
  };
8453
+ var faMagnifyingGlass = {
8454
+ prefix: "fas",
8455
+ iconName: "magnifying-glass",
8456
+ icon: [512, 512, [128269, "search"], "f002", "M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376C296.3 401.1 253.9 416 208 416 93.1 416 0 322.9 0 208S93.1 0 208 0 416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"]
8457
+ };
8458
+ var faArrowsUpToLine = {
8459
+ prefix: "fas",
8460
+ iconName: "arrows-up-to-line",
8461
+ icon: [448, 512, [], "e4c2", "M32 0C14.3 0 0 14.3 0 32S14.3 64 32 64l384 0c17.7 0 32-14.3 32-32S433.7 0 416 0L32 0zm86.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-64 64c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L64 237.3 64 480c0 17.7 14.3 32 32 32s32-14.3 32-32l0-242.7 9.4 9.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-64-64zm256 0c-12.5-12.5-32.8-12.5-45.3 0l-64 64c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l9.4-9.4 0 242.7c0 17.7 14.3 32 32 32s32-14.3 32-32l0-242.7 9.4 9.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-64-64z"]
8462
+ };
8453
8463
  var faEquals = {
8454
8464
  prefix: "fas",
8455
8465
  iconName: "equals",
@@ -8460,6 +8470,16 @@ var faChevronUp = {
8460
8470
  iconName: "chevron-up",
8461
8471
  icon: [448, 512, [], "f077", "M201.4 105.4c12.5-12.5 32.8-12.5 45.3 0l192 192c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L224 173.3 54.6 342.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l192-192z"]
8462
8472
  };
8473
+ var faFolderOpen = {
8474
+ prefix: "fas",
8475
+ iconName: "folder-open",
8476
+ icon: [576, 512, [128194, 128449, 61717], "f07c", "M56 225.6L32.4 296.2 32.4 96c0-35.3 28.7-64 64-64l138.7 0c13.8 0 27.3 4.5 38.4 12.8l38.4 28.8c5.5 4.2 12.3 6.4 19.2 6.4l117.3 0c35.3 0 64 28.7 64 64l0 16-365.4 0c-41.3 0-78 26.4-91.1 65.6zM477.8 448L99 448c-32.8 0-55.9-32.1-45.5-63.2l48-144C108 221.2 126.4 208 147 208l378.8 0c32.8 0 55.9 32.1 45.5 63.2l-48 144c-6.5 19.6-24.9 32.8-45.5 32.8z"]
8477
+ };
8478
+ var faArrowsUpDown = {
8479
+ prefix: "fas",
8480
+ iconName: "arrows-up-down",
8481
+ icon: [256, 512, ["arrows-v"], "f07d", "M150.6-22.6c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L96 77.3 96 434.7 54.6 393.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l96 96c6 6 14.1 9.4 22.6 9.4s16.6-3.4 22.6-9.4l96-96c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-41.4 41.4 0-357.5 41.4 41.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-96-96z"]
8482
+ };
8463
8483
  var faCode = {
8464
8484
  prefix: "fas",
8465
8485
  iconName: "code",
@@ -8470,6 +8490,16 @@ var faTerminal = {
8470
8490
  iconName: "terminal",
8471
8491
  icon: [512, 512, [], "f120", "M9.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L146.7 256 9.4 118.6zM224 384l256 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-256 0c-17.7 0-32-14.3-32-32s14.3-32 32-32z"]
8472
8492
  };
8493
+ var faFolder = {
8494
+ prefix: "fas",
8495
+ iconName: "folder",
8496
+ icon: [512, 512, [128193, 128447, 61716, "folder-blank"], "f07b", "M64 448l384 0c35.3 0 64-28.7 64-64l0-240c0-35.3-28.7-64-64-64L298.7 80c-6.9 0-13.7-2.2-19.2-6.4L241.1 44.8C230 36.5 216.5 32 202.7 32L64 32C28.7 32 0 60.7 0 96L0 384c0 35.3 28.7 64 64 64z"]
8497
+ };
8498
+ var faArrowsToDot = {
8499
+ prefix: "fas",
8500
+ iconName: "arrows-to-dot",
8501
+ icon: [512, 512, [], "e4be", "M256 0c17.7 0 32 14.3 32 32l0 32 32 0c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-64 64c-12.5 12.5-32.8 12.5-45.3 0l-64-64c-9.2-9.2-11.9-22.9-6.9-34.9S179.1 64 192 64l32 0 0-32c0-17.7 14.3-32 32-32zM169.4 393.4l64-64c12.5-12.5 32.8-12.5 45.3 0l64 64c9.2 9.2 11.9 22.9 6.9 34.9S332.9 448 320 448l-32 0 0 32c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-32-32 0c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9zM32 224l32 0 0-32c0-12.9 7.8-24.6 19.8-29.6s25.7-2.2 34.9 6.9l64 64c12.5 12.5 12.5 32.8 0 45.3l-64 64c-9.2 9.2-22.9 11.9-34.9 6.9S64 332.9 64 320l0-32-32 0c-17.7 0-32-14.3-32-32s14.3-32 32-32zm297.4 54.6c-12.5-12.5-12.5-32.8 0-45.3l64-64c9.2-9.2 22.9-11.9 34.9-6.9S448 179.1 448 192l0 32 32 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0 0 32c0 12.9-7.8 24.6-19.8 29.6s-25.7 2.2-34.9-6.9l-64-64zM256 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"]
8502
+ };
8473
8503
  var faArrowUp = {
8474
8504
  prefix: "fas",
8475
8505
  iconName: "arrow-up",
@@ -8505,16 +8535,31 @@ var faPen = {
8505
8535
  iconName: "pen",
8506
8536
  icon: [512, 512, [128394], "f304", "M352.9 21.2L308 66.1 445.9 204 490.8 159.1C504.4 145.6 512 127.2 512 108s-7.6-37.6-21.2-51.1L455.1 21.2C441.6 7.6 423.2 0 404 0s-37.6 7.6-51.1 21.2zM274.1 100L58.9 315.1c-10.7 10.7-18.5 24.1-22.6 38.7L.9 481.6c-2.3 8.3 0 17.3 6.2 23.4s15.1 8.5 23.4 6.2l127.8-35.5c14.6-4.1 27.9-11.8 38.7-22.6L412 237.9 274.1 100z"]
8507
8537
  };
8538
+ var faMobileScreen = {
8539
+ prefix: "fas",
8540
+ iconName: "mobile-screen",
8541
+ icon: [384, 512, ["mobile-android-alt"], "f3cf", "M16 64C16 28.7 44.7 0 80 0L304 0c35.3 0 64 28.7 64 64l0 384c0 35.3-28.7 64-64 64L80 512c-35.3 0-64-28.7-64-64L16 64zM128 440c0 13.3 10.7 24 24 24l80 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-80 0c-13.3 0-24 10.7-24 24zM304 64l-224 0 0 304 224 0 0-304z"]
8542
+ };
8508
8543
  var faChevronDown = {
8509
8544
  prefix: "fas",
8510
8545
  iconName: "chevron-down",
8511
8546
  icon: [448, 512, [], "f078", "M201.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 338.7 54.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"]
8512
8547
  };
8548
+ var faArrowDownZA = {
8549
+ prefix: "fas",
8550
+ iconName: "arrow-down-z-a",
8551
+ icon: [512, 512, ["sort-alpha-desc", "sort-alpha-down-alt"], "f881", "M230.6 390.6l-80 80c-12.5 12.5-32.8 12.5-45.3 0l-80-80c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L96 370.7 96 64c0-17.7 14.3-32 32-32s32 14.3 32 32l0 306.7 25.4-25.4c12.5-12.5 32.8-12.5 45.3 0s12.5 32.8 0 45.3zM288 64c0-17.7 14.3-32 32-32l128 0c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9L397.3 160 448 160c17.7 0 32 14.3 32 32s-14.3 32-32 32l-128 0c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9L370.8 96 320 96c-17.7 0-32-14.3-32-32zM412.6 273.7l80 160c7.9 15.8 1.5 35-14.3 42.9s-35 1.5-42.9-14.3l-7.2-14.3-88.4 0-7.2 14.3c-7.9 15.8-27.1 22.2-42.9 14.3s-22.2-27.1-14.3-42.9l80-160c5.4-10.8 16.5-17.7 28.6-17.7s23.2 6.8 28.6 17.7zM384 359.6l-20.2 40.4 40.4 0-20.2-40.4z"]
8552
+ };
8513
8553
  var faTriangleExclamation = {
8514
8554
  prefix: "fas",
8515
8555
  iconName: "triangle-exclamation",
8516
8556
  icon: [512, 512, [9888, "exclamation-triangle", "warning"], "f071", "M256 0c14.7 0 28.2 8.1 35.2 21l216 400c6.7 12.4 6.4 27.4-.8 39.5S486.1 480 472 480L40 480c-14.1 0-27.2-7.4-34.4-19.5s-7.5-27.1-.8-39.5l216-400c7-12.9 20.5-21 35.2-21zm0 352a32 32 0 1 0 0 64 32 32 0 1 0 0-64zm0-192c-18.2 0-32.7 15.5-31.4 33.7l7.4 104c.9 12.5 11.4 22.3 23.9 22.3 12.6 0 23-9.7 23.9-22.3l7.4-104c1.3-18.2-13.1-33.7-31.4-33.7z"]
8517
8557
  };
8558
+ var faLock = {
8559
+ prefix: "fas",
8560
+ iconName: "lock",
8561
+ icon: [384, 512, [128274], "f023", "M128 96l0 64 128 0 0-64c0-35.3-28.7-64-64-64s-64 28.7-64 64zM64 160l0-64C64 25.3 121.3-32 192-32S320 25.3 320 96l0 64c35.3 0 64 28.7 64 64l0 224c0 35.3-28.7 64-64 64L64 512c-35.3 0-64-28.7-64-64L0 224c0-35.3 28.7-64 64-64z"]
8562
+ };
8518
8563
  var faDownload = {
8519
8564
  prefix: "fas",
8520
8565
  iconName: "download",
@@ -8530,16 +8575,36 @@ var faCopy = {
8530
8575
  iconName: "copy",
8531
8576
  icon: [448, 512, [], "f0c5", "M192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-200.6c0-17.4-7.1-34.1-19.7-46.2L370.6 17.8C358.7 6.4 342.8 0 326.3 0L192 0zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-64 0 0 16-192 0 0-256 16 0 0-64-16 0z"]
8532
8577
  };
8578
+ var faCaretDown = {
8579
+ prefix: "fas",
8580
+ iconName: "caret-down",
8581
+ icon: [320, 512, [], "f0d7", "M140.3 376.8c12.6 10.2 31.1 9.5 42.8-2.2l128-128c9.2-9.2 11.9-22.9 6.9-34.9S301.4 192 288.5 192l-256 0c-12.9 0-24.6 7.8-29.6 19.8S.7 237.5 9.9 246.6l128 128 2.4 2.2z"]
8582
+ };
8583
+ var faDesktop = {
8584
+ prefix: "fas",
8585
+ iconName: "desktop",
8586
+ icon: [512, 512, [128421, 61704, "desktop-alt"], "f390", "M64 32C28.7 32 0 60.7 0 96L0 352c0 35.3 28.7 64 64 64l144 0-16 48-72 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l272 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-72 0-16-48 144 0c35.3 0 64-28.7 64-64l0-256c0-35.3-28.7-64-64-64L64 32zM96 96l320 0c17.7 0 32 14.3 32 32l0 160c0 17.7-14.3 32-32 32L96 320c-17.7 0-32-14.3-32-32l0-160c0-17.7 14.3-32 32-32z"]
8587
+ };
8533
8588
  var faArrowDown = {
8534
8589
  prefix: "fas",
8535
8590
  iconName: "arrow-down",
8536
8591
  icon: [384, 512, [8595], "f063", "M169.4 502.6c12.5 12.5 32.8 12.5 45.3 0l160-160c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 402.7 224 32c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 370.7-105.4-105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l160 160z"]
8537
8592
  };
8593
+ var faArrowDownAZ = {
8594
+ prefix: "fas",
8595
+ iconName: "arrow-down-a-z",
8596
+ icon: [512, 512, ["sort-alpha-asc", "sort-alpha-down"], "f15d", "M230.6 390.6l-80 80c-12.5 12.5-32.8 12.5-45.3 0l-80-80c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L96 370.7 96 64c0-17.7 14.3-32 32-32s32 14.3 32 32l0 306.7 25.4-25.4c12.5-12.5 32.8-12.5 45.3 0s12.5 32.8 0 45.3zm182-340.9c50.7 101.3 77.3 154.7 80 160 7.9 15.8 1.5 35-14.3 42.9s-35 1.5-42.9-14.3l-7.2-14.3-88.4 0-7.2 14.3c-7.9 15.8-27.1 22.2-42.9 14.3s-22.2-27.1-14.3-42.9c2.7-5.3 29.3-58.7 80-160 5.4-10.8 16.5-17.7 28.6-17.7s23.2 6.8 28.6 17.7zM384 135.6l-20.2 40.4 40.4 0-20.2-40.4zM288 320c0-17.7 14.3-32 32-32l128 0c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9L397.3 416 448 416c17.7 0 32 14.3 32 32s-14.3 32-32 32l-128 0c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l73.4-73.4-50.7 0c-17.7 0-32-14.3-32-32z"]
8597
+ };
8538
8598
  var faCircleInfo = {
8539
8599
  prefix: "fas",
8540
8600
  iconName: "circle-info",
8541
8601
  icon: [512, 512, ["info-circle"], "f05a", "M256 512a256 256 0 1 0 0-512 256 256 0 1 0 0 512zM224 160a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm-8 64l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z"]
8542
8602
  };
8603
+ var faTabletScreenButton = {
8604
+ prefix: "fas",
8605
+ iconName: "tablet-screen-button",
8606
+ icon: [448, 512, ["tablet-alt"], "f3fa", "M0 64C0 28.7 28.7 0 64 0L384 0c35.3 0 64 28.7 64 64l0 384c0 35.3-28.7 64-64 64L64 512c-35.3 0-64-28.7-64-64L0 64zM256 432a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zM384 64l-320 0 0 288 320 0 0-288z"]
8607
+ };
8543
8608
  function createDefaultRecordApi(apiUrl, repo, getToken) {
8544
8609
  const opts = () => ({ token: getToken() });
8545
8610
  return {
@@ -8551,7 +8616,7 @@ function createDefaultRecordApi(apiUrl, repo, getToken) {
8551
8616
  args: req.args,
8552
8617
  actor: none$1,
8553
8618
  limits: none$1
8554
- }, opts());
8619
+ }, opts(), req.idempotencyKey);
8555
8620
  },
8556
8621
  async history(workspace, record, limit2, from2) {
8557
8622
  return workspaceRecordHistory(apiUrl, repo, workspace, record, limit2, opts(), from2);
@@ -8605,7 +8670,9 @@ function errorOfMutationResult(result) {
8605
8670
  case "conflict":
8606
8671
  return {
8607
8672
  kind: variant("conflict", { attempts: outcome.value.attempts }),
8608
- message: `compare-and-swap conflicted after ${outcome.value.attempts} attempts; try again`,
8673
+ // A write the record no longer matches would disagree again: only
8674
+ // a lost race is worth trying again as it was.
8675
+ message: outcome.value.detail.type === "some" ? `the write no longer matches the record (${outcome.value.detail.value}); re-read it and resubmit` : `compare-and-swap conflicted after ${outcome.value.attempts} attempts; try again`,
8609
8676
  stderr: ""
8610
8677
  };
8611
8678
  default:
@@ -8631,13 +8698,13 @@ class RecordRuntime extends TrackedChannelStore {
8631
8698
  __publicField(this, "signatureCache", /* @__PURE__ */ new Map());
8632
8699
  // History per channel, fetched once + refreshed on commit.
8633
8700
  __publicField(this, "histories", /* @__PURE__ */ new Map());
8634
- __publicField(this, "historyInFlight", /* @__PURE__ */ new Set());
8701
+ __publicField(this, "historyInFlight", /* @__PURE__ */ new Map());
8635
8702
  // Channels whose last history fetch failed. Guards `history()` from
8636
8703
  // re-issuing the request on every render (a failing endpoint would
8637
8704
  // otherwise spin); cleared on the next commit / on clear() so a later
8638
8705
  // mutation retries.
8639
8706
  __publicField(this, "historyFailed", /* @__PURE__ */ new Set());
8640
- // Compiled-handle cache (issue #106 perf): buildHandle compiles 8 + (one per
8707
+ // Compiled-handle cache (issue #106 perf): buildHandle compiles 8 + (two per
8641
8708
  // mutation) East.functions per bind, and binds re-run every reactive frame.
8642
8709
  // The method IR is a pure function of the record name (which fixes the handle
8643
8710
  // type), and the methods resolve cache/api/ws LIVE, so a cached handle still
@@ -8715,11 +8782,17 @@ class RecordRuntime extends TrackedChannelStore {
8715
8782
  }
8716
8783
  return null;
8717
8784
  }
8718
- /** Fetch a record's history once per channel (deduped); notify on settle. */
8719
- fetchHistory(workspace, record, key) {
8720
- if (this.historyInFlight.has(key)) return;
8721
- this.historyInFlight.add(key);
8722
- void (async () => {
8785
+ /**
8786
+ * Fetch a record's history once per channel (deduped); notify on settle.
8787
+ *
8788
+ * @param again - Fetch once more after a fetch in flight, which may have
8789
+ * read the chain before what the caller fetches it for
8790
+ * @returns The fetch, settled once the history or its failure is in
8791
+ */
8792
+ fetchHistory(workspace, record, key, again = false) {
8793
+ const inFlight = this.historyInFlight.get(key);
8794
+ if (inFlight !== void 0) return again ? inFlight.then(() => this.fetchHistory(workspace, record, key)) : inFlight;
8795
+ const fetch = (async () => {
8723
8796
  const api3 = this.api;
8724
8797
  try {
8725
8798
  if (!api3) throw new Error("no RecordApi installed");
@@ -8733,43 +8806,67 @@ class RecordRuntime extends TrackedChannelStore {
8733
8806
  this.notify(key);
8734
8807
  }
8735
8808
  })();
8809
+ this.historyInFlight.set(key, fetch);
8810
+ return fetch;
8736
8811
  }
8737
8812
  // ----- closure semantics -------------------------------------------------
8738
- launchMutation(workspace, record, mutation, argTypes, args) {
8813
+ /**
8814
+ * Run one mutation on the record's channel, and settle to the server's
8815
+ * outcome.
8816
+ *
8817
+ * @remarks
8818
+ * The channel shows the write as it shows every launch, latest-wins; the
8819
+ * outcome returned is the server's own, whatever became of the channel. A
8820
+ * commit refreshes the record's bytes and drops its history. A conflict
8821
+ * fetches both again before the outcome settles, so an awaiting caller
8822
+ * reads the state and the history its write lost to.
8823
+ *
8824
+ * @param idempotencyKey - The write's request id, when it has one
8825
+ * @returns The outcome
8826
+ */
8827
+ runMutation(workspace, record, mutation, argTypes, args, idempotencyKey) {
8739
8828
  const key = recordChannelKey(workspace, record);
8740
8829
  const { entry, settle } = this.beginLaunch(key, (e3) => {
8741
8830
  delete e3.error;
8742
8831
  });
8743
8832
  const run = (async () => {
8744
- var _a2;
8833
+ var _a2, _b2;
8745
8834
  const invalid = await this.validate(workspace, record, mutation, argTypes);
8746
8835
  if (invalid) {
8747
8836
  settle((e3) => {
8748
8837
  e3.status = "failed";
8749
8838
  e3.error = invalid;
8750
8839
  });
8751
- return;
8840
+ return invalid.kind.type === "transport" ? variant("transport", { message: invalid.message }) : variant("invalid", { message: invalid.message });
8752
8841
  }
8753
8842
  const api3 = this.api;
8754
8843
  if (!api3) {
8844
+ const error3 = transportError("no RecordApi installed");
8755
8845
  settle((e3) => {
8756
8846
  e3.status = "failed";
8757
- e3.error = transportError("no RecordApi installed");
8847
+ e3.error = error3;
8758
8848
  });
8759
- return;
8849
+ return variant("transport", { message: error3.message });
8760
8850
  }
8761
8851
  let result;
8762
8852
  try {
8763
8853
  const encoded = args.map((arg, i) => encodeBeast2For(argTypes[i])(arg));
8764
- result = await api3.mutate(workspace, record, mutation, { args: encoded });
8854
+ result = await api3.mutate(
8855
+ workspace,
8856
+ record,
8857
+ mutation,
8858
+ idempotencyKey === void 0 ? { args: encoded } : { args: encoded, idempotencyKey }
8859
+ );
8765
8860
  } catch (err) {
8861
+ const error3 = transportError(err instanceof Error ? err.message : String(err));
8766
8862
  settle((e3) => {
8767
8863
  e3.status = "failed";
8768
- e3.error = transportError(err instanceof Error ? err.message : String(err));
8864
+ e3.error = error3;
8769
8865
  });
8770
- return;
8866
+ return variant("transport", { message: error3.message });
8771
8867
  }
8772
- if (result.outcome.type === "committed") {
8868
+ const outcome = result.outcome;
8869
+ if (outcome.type === "committed") {
8773
8870
  settle((e3) => {
8774
8871
  e3.status = "committed";
8775
8872
  delete e3.error;
@@ -8783,13 +8880,21 @@ class RecordRuntime extends TrackedChannelStore {
8783
8880
  e3.status = "failed";
8784
8881
  e3.error = errorOfMutationResult(result);
8785
8882
  });
8883
+ if (outcome.type === "conflict") {
8884
+ this.histories.delete(key);
8885
+ this.historyFailed.delete(key);
8886
+ await Promise.all([(_b2 = this.cache) == null ? void 0 : _b2.refresh(workspace), this.fetchHistory(workspace, record, key, true)]);
8887
+ }
8786
8888
  }
8889
+ return outcome;
8787
8890
  })();
8788
- entry.inflight = run;
8789
- void run.finally(() => {
8891
+ const inflight = run.then(() => void 0, () => void 0);
8892
+ entry.inflight = inflight;
8893
+ void inflight.then(() => {
8790
8894
  const current = this.entries.get(key);
8791
- if (current && current.inflight === run) delete current.inflight;
8895
+ if (current && current.inflight === inflight) delete current.inflight;
8792
8896
  });
8897
+ return run;
8793
8898
  }
8794
8899
  /**
8795
8900
  * The low-level primitives backing handle methods, bound to THIS runtime.
@@ -8835,7 +8940,7 @@ class RecordRuntime extends TrackedChannelStore {
8835
8940
  runtime.track(key);
8836
8941
  const cached = runtime.histories.get(key);
8837
8942
  if (cached === void 0) {
8838
- if (!runtime.historyFailed.has(key)) runtime.fetchHistory(ws, name, key);
8943
+ if (!runtime.historyFailed.has(key)) void runtime.fetchHistory(ws, name, key);
8839
8944
  return none$1;
8840
8945
  }
8841
8946
  return some(cached);
@@ -8879,8 +8984,21 @@ class RecordRuntime extends TrackedChannelStore {
8879
8984
  const obj = argsStruct;
8880
8985
  const argTypes = fields.map((f2) => f2.type);
8881
8986
  const args = fields.map((f2) => obj[f2.name]);
8882
- runtime.launchMutation(runtime.resolveWorkspace(), recordNameArg, mutationNameArg, argTypes, args);
8987
+ void runtime.runMutation(runtime.resolveWorkspace(), recordNameArg, mutationNameArg, argTypes, args);
8883
8988
  return null;
8989
+ }),
8990
+ RecordBindPrimitives.commit.implement((argsStructType) => async (recordNameArg, mutationNameArg, requestArg, argsStruct) => {
8991
+ const fields = argsStructType.value;
8992
+ const obj = argsStruct;
8993
+ const request = requestArg;
8994
+ return runtime.runMutation(
8995
+ runtime.resolveWorkspace(),
8996
+ recordNameArg,
8997
+ mutationNameArg,
8998
+ fields.map((f2) => f2.type),
8999
+ fields.map((f2) => obj[f2.name]),
9000
+ request === "" ? void 0 : request
9001
+ );
8884
9002
  })
8885
9003
  ];
8886
9004
  }
@@ -8892,6 +9010,7 @@ class RecordRuntime extends TrackedChannelStore {
8892
9010
  * serializable East data (issue #106).
8893
9011
  */
8894
9012
  buildHandle(handleType, name) {
9013
+ var _a2;
8895
9014
  const cached = this.handleCache.get(name);
8896
9015
  if (cached) return cached;
8897
9016
  const sig = signatureOfRecordHandleType(handleType);
@@ -8901,6 +9020,7 @@ class RecordRuntime extends TrackedChannelStore {
8901
9020
  const statusRet = fnOut(fields, "status");
8902
9021
  const historyRet = fnOut(fields, "history");
8903
9022
  const mfields = fields.find((f2) => f2.name === "mutate").type.value;
9023
+ const cfields = (_a2 = fields.find((f2) => f2.name === "commit")) == null ? void 0 : _a2.type.value;
8904
9024
  const nameExpr = East.value(name, StringType);
8905
9025
  const platform = this.buildPrimitives();
8906
9026
  const P2 = RecordBindPrimitives;
@@ -8918,6 +9038,7 @@ class RecordRuntime extends TrackedChannelStore {
8918
9038
  $3.return(P2.mutateCancel(nameExpr));
8919
9039
  }), platform)
8920
9040
  };
9041
+ const commit = {};
8921
9042
  for (const [mutationName, argTypes] of sig.mutations) {
8922
9043
  const argTypesEast = argTypes.map((t4) => fromEastTypeValue(t4));
8923
9044
  const ArgsStruct = StructType(Object.fromEntries(argTypesEast.map((t4, i) => [`arg${i}`, t4])));
@@ -8929,6 +9050,14 @@ class RecordRuntime extends TrackedChannelStore {
8929
9050
  });
8930
9051
  $3.return(P2.mutate([ArgsStruct], nameExpr, mutationNameExpr, East.value(obj, ArgsStruct)));
8931
9052
  }), platform);
9053
+ if (cfields === void 0) continue;
9054
+ commit[mutationName] = East.compileAsync(East.asyncFunction([StringType, ...argTypesEast], fnOut(cfields, mutationName), ($3, request, ...args) => {
9055
+ const obj = {};
9056
+ args.forEach((a2, i) => {
9057
+ obj[`arg${i}`] = a2;
9058
+ });
9059
+ $3.return(P2.commit([ArgsStruct], nameExpr, mutationNameExpr, request, East.value(obj, ArgsStruct)));
9060
+ }), platform);
8932
9061
  }
8933
9062
  const handle = {
8934
9063
  read: East.compile(East.function([], stateTypeEast, ($3) => {
@@ -8941,6 +9070,7 @@ class RecordRuntime extends TrackedChannelStore {
8941
9070
  $3.return(P2.history(nameExpr));
8942
9071
  }), platform),
8943
9072
  mutate,
9073
+ ...cfields !== void 0 && { commit },
8944
9074
  start: East.compile(East.function([], NullType, ($3) => {
8945
9075
  $3.return(P2.start(nameExpr));
8946
9076
  }), platform),
@@ -8985,7 +9115,7 @@ function createScopedRecordPlatform(records) {
8985
9115
  ];
8986
9116
  }
8987
9117
  function createInMemoryRecordApi(cache3, workspace, defs2) {
8988
- const compiled = /* @__PURE__ */ new Map();
9118
+ const compiled2 = /* @__PURE__ */ new Map();
8989
9119
  for (const def of defs2) {
8990
9120
  const stateType = toEastTypeValue(def.stateType);
8991
9121
  const mutations = /* @__PURE__ */ new Map();
@@ -9001,12 +9131,12 @@ function createInMemoryRecordApi(cache3, workspace, defs2) {
9001
9131
  at: /* @__PURE__ */ new Date(0),
9002
9132
  delta: none$1
9003
9133
  };
9004
- compiled.set(def.name, { stateType, mutations, commits: [genesis], seq: 0 });
9134
+ compiled2.set(def.name, { stateType, mutations, commits: [genesis], seq: 0 });
9005
9135
  void cache3.write(workspace, recordPath(def.name), encodeBeast2For(stateType)(def.initial));
9006
9136
  }
9007
9137
  return {
9008
9138
  async describe(_ws, record) {
9009
- const c2 = compiled.get(record);
9139
+ const c2 = compiled2.get(record);
9010
9140
  if (!c2) throw new Error(`no in-memory record "${record}"`);
9011
9141
  return {
9012
9142
  name: record,
@@ -9014,14 +9144,24 @@ function createInMemoryRecordApi(cache3, workspace, defs2) {
9014
9144
  };
9015
9145
  },
9016
9146
  async mutate(ws, record, mutation, req) {
9017
- const c2 = compiled.get(record);
9147
+ var _a2;
9148
+ const c2 = compiled2.get(record);
9018
9149
  if (!c2) throw new Error(`no in-memory record "${record}"`);
9019
9150
  const m2 = c2.mutations.get(mutation);
9020
9151
  if (!m2) return { outcome: variant("invalid", { message: `no mutation "${mutation}"` }) };
9152
+ if (req.idempotencyKey !== void 0 && ((_a2 = c2.keyed) == null ? void 0 : _a2.key) === req.idempotencyKey) return c2.keyed.result;
9021
9153
  const current = cache3.read(ws, recordPath(record));
9022
9154
  const state = current !== void 0 ? decodeBeast2For(c2.stateType)(current) : void 0;
9023
9155
  const args = req.args.map((bytes, i) => decodeBeast2For(m2.argTypes[i])(bytes));
9024
- const next2 = m2.reduce(state, ...args);
9156
+ let next2;
9157
+ try {
9158
+ next2 = m2.reduce(state, ...args);
9159
+ } catch (err) {
9160
+ if (err instanceof ConflictError) {
9161
+ return { outcome: variant("conflict", { attempts: 1n, detail: some(`primary: ${err.message}`) }) };
9162
+ }
9163
+ return { outcome: variant("failed", { exitCode: 1n, stderr: err instanceof Error ? err.message : String(err) }) };
9164
+ }
9025
9165
  await cache3.write(ws, recordPath(record), encodeBeast2For(c2.stateType)(next2));
9026
9166
  c2.seq += 1;
9027
9167
  const hash2 = `${record}-${c2.seq}`.padEnd(64, "0");
@@ -9034,10 +9174,12 @@ function createInMemoryRecordApi(cache3, workspace, defs2) {
9034
9174
  at: /* @__PURE__ */ new Date(0),
9035
9175
  delta: none$1
9036
9176
  });
9037
- return { outcome: variant("committed", { commitHash: hash2, stateHash: `${record}-state-${c2.seq}`.padEnd(64, "0") }) };
9177
+ const result = { outcome: variant("committed", { commitHash: hash2, stateHash: `${record}-state-${c2.seq}`.padEnd(64, "0") }) };
9178
+ c2.keyed = req.idempotencyKey !== void 0 ? { key: req.idempotencyKey, result } : void 0;
9179
+ return result;
9038
9180
  },
9039
9181
  async history(_ws, record, limit2) {
9040
- const c2 = compiled.get(record);
9182
+ const c2 = compiled2.get(record);
9041
9183
  if (!c2) throw new Error(`no in-memory record "${record}"`);
9042
9184
  const commits = limit2 !== void 0 ? c2.commits.slice(0, limit2) : c2.commits;
9043
9185
  return { commits };
@@ -64183,6 +64325,1711 @@ const EastChakraDecisionJournal = memo(function EastChakraDecisionJournal2({ val
64183
64325
  ] });
64184
64326
  });
64185
64327
  implementUIComponent(DecisionJournal.Component, EastChakraDecisionJournal);
64328
+ const studioMessages = {
64329
+ statusDraft: () => "Draft",
64330
+ statusLive: () => "Live",
64331
+ statusLiveEdited: () => "Live · edited",
64332
+ statusTemplate: () => "Template",
64333
+ publish: () => "Publish",
64334
+ noPageOpen: () => "No page open",
64335
+ noPageOpenHint: ({ project, page }) => `${project} has no page ${page}. Open a page from the palette's Pages tab, or start one from the page library.`,
64336
+ components: () => "Components",
64337
+ componentNoun: () => ({ singular: "component", plural: "components" }),
64338
+ pageNoun: () => ({ singular: "page", plural: "pages" }),
64339
+ logicFixed: () => "Logic fixed by the developer",
64340
+ category: () => "Category",
64341
+ tags: () => "Tags",
64342
+ collections: () => "Collections",
64343
+ inspector: () => "Inspector",
64344
+ spanBadge: ({ span }) => `${span}/12`,
64345
+ noComponent: ({ key }) => `No component "${key}"`,
64346
+ noComponentHint: () => "This surface lists no component with this key.",
64347
+ twoComponents: ({ key }) => `Two components share the key "${key}"`,
64348
+ twoComponentsHint: () => "A surface lists each component once.",
64349
+ notPublished: ({ page }) => `${page} is not published yet`,
64350
+ notPublishedHint: () => "Publish it to show it here.",
64351
+ noPage: ({ page }) => `No page ${page}`,
64352
+ noPageHint: ({ project }) => `The project ${project} has no page by this name.`,
64353
+ blankSummary: () => "12-col · empty",
64354
+ placements: ({ n: n2, count }) => `${count} ${n2 === 1 ? "component" : "components"}`,
64355
+ openInBuilder: () => "Open in builder →",
64356
+ newPageFromTemplate: () => "New page from template",
64357
+ selectedComponent: () => "Selected component",
64358
+ logicChanged: () => "logic changed since this page went live",
64359
+ data: () => "Data",
64360
+ readsNothing: () => "reads no data",
64361
+ configuration: () => "Configuration",
64362
+ fixedByDeveloper: () => "fixed by developer",
64363
+ noDescription: () => "No description",
64364
+ layout: () => "Layout",
64365
+ columnSpan: () => "Column span",
64366
+ spanOf: ({ span }) => `${span} / 12`,
64367
+ decreaseSpan: () => "Decrease span",
64368
+ increaseSpan: () => "Increase span",
64369
+ row: () => "Row",
64370
+ height: () => "Height",
64371
+ auto: () => "Auto",
64372
+ px: ({ px }) => `${px} px`,
64373
+ align: () => "Align",
64374
+ alignTop: () => "Top",
64375
+ alignCenter: () => "Center",
64376
+ alignStretch: () => "Stretch",
64377
+ published: () => "Published component · logic immutable",
64378
+ nothingSelected: () => "Nothing selected",
64379
+ nothingSelectedHint: () => "Click a component on the grid to see what it reads and its layout.",
64380
+ searchLibrary: ({ pages, templates, np, nt }) => `Search ${pages} ${np === 1 ? "page" : "pages"} and ${templates} ${nt === 1 ? "template" : "templates"}…`,
64381
+ searchLabel: () => "Search pages and templates",
64382
+ clearSearch: () => "Clear search",
64383
+ sortByName: () => "Sort · Name",
64384
+ nameAz: () => "Name A–Z",
64385
+ nameZa: () => "Name Z–A",
64386
+ newPageIn: ({ project }) => `New page in ${project}`,
64387
+ newPage: () => "New page",
64388
+ projects: () => "Projects",
64389
+ pages: () => "Pages",
64390
+ live: () => "Live",
64391
+ draft: () => "Draft",
64392
+ templates: () => "Templates",
64393
+ cloneToStart: () => "clone to start a page",
64394
+ pagesIn: ({ shown, total, project, narrowed }) => narrowed ? `${shown} of ${total} in ${project}` : `${total} in ${project}`,
64395
+ pageName: () => "Page name",
64396
+ pageNameMissing: () => "Give the page a name to create it.",
64397
+ template: () => "Template",
64398
+ blankGrid: () => "Blank grid",
64399
+ createPage: () => "Create page",
64400
+ cancel: () => "Cancel",
64401
+ nameTaken: ({ name }) => `${name} is already a page or a template here.`,
64402
+ saveAsTemplate: () => "Save as template",
64403
+ templateName: () => "Template name",
64404
+ templateNameMissing: () => "Give the template a name to save it.",
64405
+ saveTemplate: () => "Save template",
64406
+ templateNameFor: ({ page }) => `${page} template`,
64407
+ templateOpen: () => "A template is open — open a page to save it as a template",
64408
+ preview: () => "Preview",
64409
+ devices: () => "Device",
64410
+ device: ({ device }) => device === "desktop" ? "Desktop" : device === "tablet" ? "Tablet" : "Mobile",
64411
+ env: () => "Env",
64412
+ exit: () => "Exit",
64413
+ readyToPublish: () => "Ready to publish",
64414
+ upToDate: () => "Up to date",
64415
+ templateNotPublished: () => "Templates are not published",
64416
+ version: ({ version: version2 }) => `v${version2}`,
64417
+ liveVersion: () => "live",
64418
+ templateKind: () => "template",
64419
+ changesSince: ({ n: n2, count, version: version2 }) => `${count} ${n2 === 1 ? "change" : "changes"} since ${version2}`,
64420
+ changesFirst: ({ n: n2, count }) => `${count} ${n2 === 1 ? "change" : "changes"} · first version`,
64421
+ noChangesSince: ({ version: version2 }) => `No changes since ${version2}`,
64422
+ changeVerb: ({ change }) => {
64423
+ switch (change) {
64424
+ case "added":
64425
+ return "Added";
64426
+ case "removed":
64427
+ return "Removed";
64428
+ case "moved":
64429
+ return "Moved";
64430
+ case "resized":
64431
+ case "height":
64432
+ return "Resized";
64433
+ case "aligned":
64434
+ return "Aligned";
64435
+ case "retitled":
64436
+ return "Retitled";
64437
+ }
64438
+ },
64439
+ logicUnchanged: () => "Component logic unchanged — only layout changed. Safe to publish.",
64440
+ logicChangedIn: ({ version: version2, components: components2 }) => {
64441
+ const names = components2.length < 2 ? components2.join("") : `${components2.slice(0, -1).join(", ")} and ${components2.at(-1)}`;
64442
+ const its = components2.length === 1 ? "its" : "their";
64443
+ return `Logic changed since ${version2} in ${names} — ${its} placements publish with ${its} new code`;
64444
+ },
64445
+ audience: () => "Audience",
64446
+ rollout: () => "Rollout",
64447
+ saveAsDraft: () => "Save as draft",
64448
+ publishTo: ({ version: version2, env }) => version2 === void 0 ? "Publish" : env === void 0 ? `Publish ${version2}` : `Publish ${version2} to ${env}`
64449
+ };
64450
+ const StudioMessagesContext = createContext(studioMessages);
64451
+ function useStudioMessages() {
64452
+ return useContext(StudioMessagesContext);
64453
+ }
64454
+ function StudioMessagesProvider({ messages, children: children2 }) {
64455
+ const parent4 = useStudioMessages();
64456
+ const value = useMemo(() => ({ ...parent4, ...messages }), [parent4, messages]);
64457
+ return createElement$1(StudioMessagesContext.Provider, { value }, children2);
64458
+ }
64459
+ const LEAST_SPAN = 2;
64460
+ const HEIGHTS = [160, 240, 320, 400, 480];
64461
+ const ALIGNS = [
64462
+ { align: "top", icon: faArrowsUpToLine, name: (m2) => m2.alignTop() },
64463
+ { align: "center", icon: faArrowsToDot, name: (m2) => m2.alignCenter() },
64464
+ { align: "stretch", icon: faArrowsUpDown, name: (m2) => m2.alignStretch() }
64465
+ ];
64466
+ function RowField({ row, onRow, css: css2, id: id3 }) {
64467
+ const [text, setText] = useState(String(row));
64468
+ useEffect(() => {
64469
+ setText(String(row));
64470
+ }, [row]);
64471
+ const commit = () => {
64472
+ const asked = Number.parseInt(text, 10);
64473
+ if (!Number.isInteger(asked) || asked < 1 || asked === row) {
64474
+ setText(String(row));
64475
+ return;
64476
+ }
64477
+ onRow(asked);
64478
+ };
64479
+ const onKeyDown = (e3) => {
64480
+ if (e3.key === "Enter") {
64481
+ e3.preventDefault();
64482
+ commit();
64483
+ } else if (e3.key === "Escape") {
64484
+ e3.preventDefault();
64485
+ setText(String(row));
64486
+ } else if (e3.key === "ArrowUp") {
64487
+ e3.preventDefault();
64488
+ onRow(row + 1);
64489
+ } else if (e3.key === "ArrowDown" && row > 1) {
64490
+ e3.preventDefault();
64491
+ onRow(row - 1);
64492
+ }
64493
+ };
64494
+ return /* @__PURE__ */ jsx$1(
64495
+ chakra.input,
64496
+ {
64497
+ id: id3,
64498
+ css: css2,
64499
+ value: text,
64500
+ inputMode: "numeric",
64501
+ autoComplete: "off",
64502
+ "data-inspector-row": "",
64503
+ onChange: (e3) => setText(e3.target.value.replace(/[^0-9]/g, "")),
64504
+ onBlur: commit,
64505
+ onKeyDown
64506
+ }
64507
+ );
64508
+ }
64509
+ const StudioInspector = memo(function StudioInspector2({ value }) {
64510
+ const styles2 = useSlotRecipe({ key: "studioInspector" })();
64511
+ const stepper = useSlotRecipe({ key: "stepper" })({ tone: "brand", size: "md" });
64512
+ const seg = useSlotRecipe({ key: "seg" })();
64513
+ const input = useRecipe({ key: "input" })({ variant: "numeric", size: "sm" });
64514
+ const m2 = useStudioMessages();
64515
+ const words = useFormatters();
64516
+ const rowId = useId();
64517
+ const selection2 = value.selection.type === "some" ? value.selection.value : void 0;
64518
+ const onRequest = value.onRequest;
64519
+ const key = selection2 == null ? void 0 : selection2.key;
64520
+ const ask = useCallback((change) => {
64521
+ if (key === void 0) return;
64522
+ try {
64523
+ onRequest({ key, change });
64524
+ } catch (err) {
64525
+ console.error("[Studio.Builder] the inspector's layout request failed:", err);
64526
+ }
64527
+ }, [key, onRequest]);
64528
+ const height2 = selection2 !== void 0 && selection2.layout.height.type === "some" ? Number(selection2.layout.height.value) : void 0;
64529
+ const heights = useMemo(() => createListCollection({
64530
+ items: [
64531
+ { value: "auto", label: m2.auto(), px: void 0 },
64532
+ ...[.../* @__PURE__ */ new Set([...HEIGHTS, ...height2 !== void 0 ? [height2] : []])].sort((a2, b2) => a2 - b2).map((px) => ({ value: String(px), label: m2.px({ px: words.bare(px) }), px }))
64533
+ ]
64534
+ }), [height2, m2, words]);
64535
+ if (selection2 === void 0) {
64536
+ return /* @__PURE__ */ jsx$1(Box, { css: styles2.root, "data-studio-inspector": "", children: /* @__PURE__ */ jsxs(Box, { css: styles2.empty, "data-inspector": "empty", children: [
64537
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.emptyTitle, children: m2.nothingSelected() }),
64538
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.emptyHint, children: m2.nothingSelectedHint() })
64539
+ ] }) });
64540
+ }
64541
+ const layout4 = selection2.layout;
64542
+ const span = Number(layout4.span);
64543
+ const most = Number(layout4.most);
64544
+ const description = selection2.description.type === "some" ? selection2.description.value : void 0;
64545
+ const aligned = layout4.align.type;
64546
+ const heightKey = height2 === void 0 ? "auto" : String(height2);
64547
+ return /* @__PURE__ */ jsxs(Box, { css: styles2.root, "data-studio-inspector": "", children: [
64548
+ /* @__PURE__ */ jsxs(Box, { css: styles2.selection, "data-inspector": "selection", children: [
64549
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.eyebrow, children: m2.selectedComponent() }),
64550
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.name, "data-inspector-name": "", children: selection2.name }),
64551
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.meta, "data-inspector-meta": "", children: selection2.component }),
64552
+ selection2.changed && /* @__PURE__ */ jsxs(Box, { as: "span", css: styles2.warning, "data-inspector-changed": "", children: [
64553
+ /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faTriangleExclamation }),
64554
+ m2.logicChanged()
64555
+ ] })
64556
+ ] }),
64557
+ /* @__PURE__ */ jsxs(Box, { css: styles2.data, "data-inspector": "data", children: [
64558
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.eyebrow, children: m2.data() }),
64559
+ selection2.reads.length > 0 ? /* @__PURE__ */ jsx$1(Box, { as: "ul", css: styles2.reads, "aria-label": m2.data(), children: selection2.reads.map((path2) => {
64560
+ const keypath = pathToString$1(path2);
64561
+ return /* @__PURE__ */ jsx$1(Box, { as: "li", css: styles2.read, children: keypath }, keypath);
64562
+ }) }) : /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.noReads, children: m2.readsNothing() })
64563
+ ] }),
64564
+ /* @__PURE__ */ jsxs(Box, { css: styles2.config, "data-inspector": "config", children: [
64565
+ /* @__PURE__ */ jsxs(Box, { css: styles2.configHead, children: [
64566
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.eyebrow, children: m2.configuration() }),
64567
+ /* @__PURE__ */ jsxs(Box, { as: "span", css: styles2.lockNote, children: [
64568
+ /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faLock }),
64569
+ m2.fixedByDeveloper()
64570
+ ] })
64571
+ ] }),
64572
+ /* @__PURE__ */ jsx$1(Box, { as: "p", css: styles2.description, "data-empty": description === void 0 ? "" : void 0, children: description ?? m2.noDescription() })
64573
+ ] }),
64574
+ /* @__PURE__ */ jsxs(Box, { css: styles2.layout, "data-inspector": "layout", children: [
64575
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.eyebrow, children: m2.layout() }),
64576
+ /* @__PURE__ */ jsxs(Box, { css: styles2.field, children: [
64577
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.fieldLabel, children: m2.columnSpan() }),
64578
+ /* @__PURE__ */ jsxs(Box, { css: stepper.root, role: "group", "aria-label": m2.columnSpan(), children: [
64579
+ /* @__PURE__ */ jsx$1(
64580
+ chakra.button,
64581
+ {
64582
+ type: "button",
64583
+ css: stepper.button,
64584
+ "aria-label": m2.decreaseSpan(),
64585
+ title: m2.decreaseSpan(),
64586
+ disabled: span <= LEAST_SPAN,
64587
+ onClick: () => ask(variant("span", BigInt(span - 1))),
64588
+ children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faMinus })
64589
+ }
64590
+ ),
64591
+ /* @__PURE__ */ jsx$1(Box, { as: "output", css: stepper.value, "data-inspector-span": "", children: m2.spanOf({ span: words.number(span) }) }),
64592
+ /* @__PURE__ */ jsx$1(
64593
+ chakra.button,
64594
+ {
64595
+ type: "button",
64596
+ css: stepper.button,
64597
+ "aria-label": m2.increaseSpan(),
64598
+ title: m2.increaseSpan(),
64599
+ disabled: span >= most,
64600
+ onClick: () => ask(variant("span", BigInt(span + 1))),
64601
+ children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faPlus })
64602
+ }
64603
+ )
64604
+ ] })
64605
+ ] }),
64606
+ /* @__PURE__ */ jsxs(Box, { css: styles2.field, children: [
64607
+ /* @__PURE__ */ jsx$1(chakra.label, { css: styles2.fieldLabel, htmlFor: rowId, children: m2.row() }),
64608
+ /* @__PURE__ */ jsx$1(RowField, { row: Number(layout4.row), onRow: (row) => ask(variant("row", BigInt(row))), css: [input, styles2.rowField], id: rowId })
64609
+ ] }),
64610
+ /* @__PURE__ */ jsxs(Box, { css: styles2.field, children: [
64611
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.fieldLabel, children: m2.height() }),
64612
+ /* @__PURE__ */ jsxs(
64613
+ Select.Root,
64614
+ {
64615
+ collection: heights,
64616
+ value: [heightKey],
64617
+ size: "sm",
64618
+ variant: "numeric",
64619
+ css: styles2.heightField,
64620
+ onValueChange: (details) => {
64621
+ const picked = heights.items.find((item) => item.value === details.value[0]);
64622
+ if (picked === void 0 || picked.value === heightKey) return;
64623
+ const px = picked.px;
64624
+ queueMicrotask(() => ask(variant("height", px === void 0 ? none$1 : some(BigInt(px)))));
64625
+ },
64626
+ children: [
64627
+ /* @__PURE__ */ jsx$1(Select.HiddenSelect, {}),
64628
+ /* @__PURE__ */ jsxs(Select.Control, { children: [
64629
+ /* @__PURE__ */ jsx$1(Select.Trigger, { "aria-label": m2.height(), "data-inspector-height": "", children: /* @__PURE__ */ jsx$1(Select.ValueText, {}) }),
64630
+ /* @__PURE__ */ jsx$1(Select.IndicatorGroup, { children: /* @__PURE__ */ jsx$1(Select.Indicator, {}) })
64631
+ ] }),
64632
+ /* @__PURE__ */ jsx$1(Portal, { children: /* @__PURE__ */ jsx$1(Select.Positioner, { children: /* @__PURE__ */ jsx$1(Select.Content, { children: heights.items.map((item) => /* @__PURE__ */ jsxs(Select.Item, { item, children: [
64633
+ item.label,
64634
+ /* @__PURE__ */ jsx$1(Select.ItemIndicator, {})
64635
+ ] }, item.value)) }) }) })
64636
+ ]
64637
+ }
64638
+ )
64639
+ ] }),
64640
+ /* @__PURE__ */ jsxs(Box, { css: styles2.field, children: [
64641
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.fieldLabel, children: m2.align() }),
64642
+ /* @__PURE__ */ jsx$1(Box, { css: seg.root, role: "group", "aria-label": m2.align(), children: ALIGNS.map(({ align, icon: icon3, name }) => /* @__PURE__ */ jsx$1(
64643
+ chakra.button,
64644
+ {
64645
+ type: "button",
64646
+ css: seg.item,
64647
+ "data-state": aligned === align ? "on" : "off",
64648
+ "aria-pressed": aligned === align,
64649
+ "aria-label": name(m2),
64650
+ title: name(m2),
64651
+ onClick: () => ask(variant("align", variant(align, null))),
64652
+ children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: icon3 })
64653
+ },
64654
+ align
64655
+ )) })
64656
+ ] })
64657
+ ] }),
64658
+ /* @__PURE__ */ jsxs(Box, { css: styles2.footer, "data-inspector": "footer", children: [
64659
+ /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faLock }),
64660
+ m2.published()
64661
+ ] })
64662
+ ] });
64663
+ });
64664
+ const encodeKey = encodeBeast2For(StudioKeyType);
64665
+ const decodeKey = decodeBeast2For(StudioKeyType);
64666
+ function useOpenPage(key, first2) {
64667
+ const store = StateRuntime$1.getStore();
64668
+ const subscribe = useCallback((notify3) => store.subscribe(key, notify3), [store, key]);
64669
+ const snapshot = useCallback(() => store.read(key), [store, key]);
64670
+ const bytes = useSyncExternalStore(subscribe, snapshot);
64671
+ const open = useMemo(() => bytes === void 0 ? first2 : decodeKey(bytes), [bytes, first2]);
64672
+ const write = useCallback((next2) => {
64673
+ store.write(key, encodeKey(next2));
64674
+ }, [store, key]);
64675
+ return [open, write];
64676
+ }
64677
+ const pageEqual = equivalentFor(StudioPageComponent.schema);
64678
+ const keyEqual$1 = equalFor(StudioKeyType);
64679
+ function StudioComponentView({ component: component2, storageKey }) {
64680
+ const render3 = useCallback(() => component2.render(), [component2]);
64681
+ const { result } = useTrackedEvaluation(render3);
64682
+ if (!result.ok) {
64683
+ const message = result.error instanceof Error ? result.error.message : String(result.error);
64684
+ return /* @__PURE__ */ jsx$1(BannerView, { status: "error", title: component2.name, description: message });
64685
+ }
64686
+ return /* @__PURE__ */ jsx$1(EastChakraComponent, { value: result.value, storageKey });
64687
+ }
64688
+ function StudioPlacement({ component: key, listed, storageKey }) {
64689
+ const m2 = useStudioMessages();
64690
+ if (listed.length > 1) {
64691
+ return /* @__PURE__ */ jsx$1(BannerView, { status: "error", title: m2.twoComponents({ key }), description: m2.twoComponentsHint() });
64692
+ }
64693
+ const component2 = listed[0];
64694
+ if (component2 === void 0) {
64695
+ return /* @__PURE__ */ jsx$1(
64696
+ EmptyStateView,
64697
+ {
64698
+ icon: { prefix: "fas", name: "puzzle-piece" },
64699
+ title: m2.noComponent({ key }),
64700
+ description: m2.noComponentHint()
64701
+ }
64702
+ );
64703
+ }
64704
+ return /* @__PURE__ */ jsx$1(StudioComponentView, { component: component2, storageKey });
64705
+ }
64706
+ function StudioLayout({ cells, components: components2, storageKey }) {
64707
+ const listed = useMemo(() => {
64708
+ const byKey = /* @__PURE__ */ new Map();
64709
+ for (const component2 of components2) {
64710
+ const same2 = byKey.get(component2.key);
64711
+ if (same2 === void 0) byKey.set(component2.key, [component2]);
64712
+ else same2.push(component2);
64713
+ }
64714
+ return byKey;
64715
+ }, [components2]);
64716
+ const tiles = useMemo(() => cells.map((cell) => {
64717
+ var _a2;
64718
+ const first2 = (_a2 = listed.get(cell.component)) == null ? void 0 : _a2[0];
64719
+ return {
64720
+ key: cell.key,
64721
+ row: cell.row,
64722
+ span: cell.span,
64723
+ height: cell.height,
64724
+ align: cell.align,
64725
+ frame: first2 === void 0 ? true : first2.frame.type === "card",
64726
+ cell
64727
+ };
64728
+ }), [cells, listed]);
64729
+ return /* @__PURE__ */ jsx$1(
64730
+ SnapGridTiles,
64731
+ {
64732
+ cells: tiles,
64733
+ content: (tile) => /* @__PURE__ */ jsx$1(StudioPlacement, { component: tile.cell.component, listed: listed.get(tile.cell.component) ?? [], storageKey: `${storageKey}.${tile.key}` })
64734
+ }
64735
+ );
64736
+ }
64737
+ const EastChakraStudioPage = memo(function EastChakraStudioPage2({ value, storageKey }) {
64738
+ const m2 = useStudioMessages();
64739
+ const key = value.page;
64740
+ let entry;
64741
+ for (const [at, found] of value.pages) {
64742
+ if (keyEqual$1(at, key)) {
64743
+ entry = found;
64744
+ break;
64745
+ }
64746
+ }
64747
+ if (entry === void 0) {
64748
+ return /* @__PURE__ */ jsx$1(
64749
+ EmptyStateView,
64750
+ {
64751
+ icon: { prefix: "fas", name: "file-circle-question" },
64752
+ title: m2.noPage({ page: key.page }),
64753
+ description: m2.noPageHint({ project: key.project })
64754
+ }
64755
+ );
64756
+ }
64757
+ const layout4 = entry.type === "template" ? entry.value : value.version.type === "draft" ? entry.value.draft : entry.value.live.type === "some" ? entry.value.live.value.page : void 0;
64758
+ if (layout4 === void 0) {
64759
+ return /* @__PURE__ */ jsx$1(
64760
+ EmptyStateView,
64761
+ {
64762
+ icon: { prefix: "fas", name: "file-circle-question" },
64763
+ title: m2.notPublished({ page: key.page }),
64764
+ description: m2.notPublishedHint()
64765
+ }
64766
+ );
64767
+ }
64768
+ return /* @__PURE__ */ jsx$1(StudioLayout, { cells: layout4.cells, components: value.components, storageKey });
64769
+ }, (prev2, next2) => pageEqual(prev2.value, next2.value) && prev2.storageKey === next2.storageKey);
64770
+ implementUIComponent(StudioPageComponent, EastChakraStudioPage);
64771
+ const StudioPalette = memo(function StudioPalette2({
64772
+ components: components2,
64773
+ cards,
64774
+ pages,
64775
+ open,
64776
+ ids,
64777
+ onSelect,
64778
+ onOpen,
64779
+ storageKey
64780
+ }) {
64781
+ const m2 = useStudioMessages();
64782
+ const words = useFormatters();
64783
+ const componentsLibrary = useMemo(() => ({
64784
+ id: ids.components,
64785
+ hint: none$1,
64786
+ items: components2.map((component2) => {
64787
+ const card = cards.get(component2.key);
64788
+ return {
64789
+ key: component2.key,
64790
+ label: component2.name,
64791
+ sublabel: card === void 0 ? none$1 : some(card.meta),
64792
+ icon: some(component2.icon),
64793
+ status: none$1,
64794
+ trailing: some({ icon: "lock", label: m2.logicFixed(), tone: none$1 }),
64795
+ draggable: true,
64796
+ filtered: false,
64797
+ placed: (card == null ? void 0 : card.placed) ?? false,
64798
+ media: none$1,
64799
+ avatar: none$1,
64800
+ byline: none$1,
64801
+ action: none$1,
64802
+ search: some(`${component2.name} ${component2.category} ${component2.tags.join(" ")}`),
64803
+ groups: /* @__PURE__ */ new Map([["category", component2.category]]),
64804
+ facets: /* @__PURE__ */ new Map([["category", [component2.category]], ["tags", component2.tags], ["collections", component2.collections]]),
64805
+ dims: /* @__PURE__ */ new Map()
64806
+ };
64807
+ }),
64808
+ groupOptions: [{ key: "category", label: m2.category() }],
64809
+ groupSummaries: /* @__PURE__ */ new Map(),
64810
+ dimOptions: [],
64811
+ defaultDimensions: [],
64812
+ filterOptions: [
64813
+ { key: "category", label: m2.category() },
64814
+ { key: "tags", label: m2.tags() },
64815
+ { key: "collections", label: m2.collections() }
64816
+ ],
64817
+ searchable: true,
64818
+ noun: some(m2.componentNoun()),
64819
+ addLabel: none$1,
64820
+ onAdd: none$1,
64821
+ onCardClick: some((key) => {
64822
+ onSelect(key);
64823
+ return null;
64824
+ }),
64825
+ slice: none$1,
64826
+ style: some({ height: some("fill"), maxHeight: none$1, virtualization: some(false), columns: none$1, mediaPlacement: none$1, mediaSize: none$1 }),
64827
+ variant: none$1,
64828
+ layout: none$1,
64829
+ toolbar: true
64830
+ }), [ids.components, components2, cards, m2, onSelect]);
64831
+ const pagesLibrary = useMemo(() => ({
64832
+ id: ids.pages,
64833
+ hint: none$1,
64834
+ items: pages.map((page) => ({
64835
+ key: page.page,
64836
+ label: page.title,
64837
+ sublabel: some(page.meta),
64838
+ icon: some("file-lines"),
64839
+ status: none$1,
64840
+ trailing: some({
64841
+ icon: "circle",
64842
+ label: page.live ? m2.live() : m2.draft(),
64843
+ tone: some(page.live ? variant("success", null) : variant("neutral", null))
64844
+ }),
64845
+ draggable: false,
64846
+ filtered: false,
64847
+ placed: page.page === open,
64848
+ media: none$1,
64849
+ avatar: none$1,
64850
+ byline: none$1,
64851
+ action: none$1,
64852
+ search: some(page.title),
64853
+ groups: /* @__PURE__ */ new Map(),
64854
+ facets: /* @__PURE__ */ new Map(),
64855
+ dims: /* @__PURE__ */ new Map()
64856
+ })),
64857
+ groupOptions: [],
64858
+ groupSummaries: /* @__PURE__ */ new Map(),
64859
+ dimOptions: [],
64860
+ defaultDimensions: [],
64861
+ filterOptions: [],
64862
+ searchable: true,
64863
+ noun: some(m2.pageNoun()),
64864
+ addLabel: none$1,
64865
+ onAdd: none$1,
64866
+ onCardClick: some((key) => {
64867
+ onOpen(key);
64868
+ return null;
64869
+ }),
64870
+ slice: none$1,
64871
+ style: some({ height: some("fill"), maxHeight: none$1, virtualization: some(false), columns: none$1, mediaPlacement: none$1, mediaSize: none$1 }),
64872
+ variant: none$1,
64873
+ layout: none$1,
64874
+ toolbar: true
64875
+ }), [ids.pages, pages, open, m2, onOpen]);
64876
+ return /* @__PURE__ */ jsx$1(
64877
+ DockPane,
64878
+ {
64879
+ storageKey: `${storageKey}.palette`,
64880
+ icon: "shapes",
64881
+ label: m2.components(),
64882
+ badge: words.number(components2.length),
64883
+ expandedSize: "264px",
64884
+ railSize: "44px",
64885
+ side: "start",
64886
+ surface: "shell",
64887
+ tabs: [
64888
+ { key: "components", label: m2.components(), body: /* @__PURE__ */ jsx$1(EastChakraLibrary, { value: componentsLibrary, storageKey: `${storageKey}.palette.components` }) },
64889
+ { key: "pages", label: m2.pages(), body: /* @__PURE__ */ jsx$1(EastChakraLibrary, { value: pagesLibrary, storageKey: `${storageKey}.palette.pages` }) }
64890
+ ]
64891
+ }
64892
+ );
64893
+ });
64894
+ const DEVICES = [
64895
+ { device: "desktop", icon: faDesktop, width: 1440 },
64896
+ { device: "tablet", icon: faTabletScreenButton, width: 1024 },
64897
+ { device: "mobile", icon: faMobileScreen, width: 390 }
64898
+ ];
64899
+ const StudioPublishPreview = memo(function StudioPublishPreview2({ value, page }) {
64900
+ const styles2 = useSlotRecipe({ key: "studioPublish" })();
64901
+ const m2 = useStudioMessages();
64902
+ const words = useFormatters();
64903
+ const [device, setDevice] = useState("desktop");
64904
+ const [phase, setPhase] = useState({ kind: "idle" });
64905
+ const latest = useRef(value);
64906
+ latest.current = value;
64907
+ const summary = value.summary;
64908
+ const standing = summary.standing.type;
64909
+ const live = summary.live.type === "some" ? summary.live.value : void 0;
64910
+ const liveVersion = live === void 0 ? "" : m2.version({ version: words.number(live) });
64911
+ const nextVersion = m2.version({ version: words.number(live === void 0 ? 1n : live + 1n) });
64912
+ const env = value.env.type === "some" ? value.env.value : void 0;
64913
+ const exit = value.onExit.type === "some" ? value.onExit.value : void 0;
64914
+ const busy = phase.kind === "applying" || phase.kind === "publishing";
64915
+ const width2 = DEVICES.find((d2) => d2.device === device).width;
64916
+ const publish = useCallback(async () => {
64917
+ setPhase({ kind: "publishing" });
64918
+ let reason;
64919
+ try {
64920
+ const refused = await latest.current.onPublish();
64921
+ reason = refused.type === "some" ? refused.value : void 0;
64922
+ } catch (err) {
64923
+ reason = err instanceof Error ? err.message : String(err);
64924
+ }
64925
+ setPhase(reason === void 0 ? { kind: "idle" } : { kind: "refused", reason });
64926
+ }, []);
64927
+ const ask = (then2) => {
64928
+ const id3 = Array.from(crypto.getRandomValues(new Uint8Array(8)), (b2) => b2.toString(16).padStart(2, "0")).join("");
64929
+ setPhase({ kind: "applying", id: id3, publish: then2 === "publish" });
64930
+ const onApply = value.onApply;
64931
+ queueMicrotask(() => {
64932
+ try {
64933
+ onApply(id3);
64934
+ } catch (err) {
64935
+ setPhase({ kind: "refused", reason: err instanceof Error ? err.message : String(err) });
64936
+ }
64937
+ });
64938
+ };
64939
+ const answer = value.apply;
64940
+ useEffect(() => {
64941
+ if (phase.kind !== "applying") return;
64942
+ if (answer.type === "applied" && answer.value === phase.id) {
64943
+ if (phase.publish) void publish();
64944
+ else setPhase({ kind: "idle" });
64945
+ } else if (answer.type === "refused" && answer.value.id === phase.id) {
64946
+ setPhase({ kind: "refused", reason: answer.value.reason });
64947
+ }
64948
+ }, [answer, phase, publish]);
64949
+ const changes = summary.changes;
64950
+ const changed = summary.changed;
64951
+ const count = changes.length;
64952
+ const head = standing === "ready" ? m2.readyToPublish() : standing === "current" ? m2.upToDate() : m2.templateNotPublished();
64953
+ const listHead = live === void 0 ? m2.changesFirst({ n: count, count: words.number(count) }) : count === 0 ? m2.noChangesSince({ version: liveVersion }) : m2.changesSince({ n: count, count: words.number(count), version: liveVersion });
64954
+ const tone = changed.length === 0 ? "change" : "warning";
64955
+ const audience = value.audience.type === "some" ? value.audience.value : void 0;
64956
+ const rollout = value.rollout.type === "some" ? value.rollout.value : void 0;
64957
+ return /* @__PURE__ */ jsxs(Box, { css: styles2.root, "data-studio-publish": "", children: [
64958
+ /* @__PURE__ */ jsxs(Box, { css: styles2.bar, "data-publish-bar": "", children: [
64959
+ /* @__PURE__ */ jsxs(Box, { as: "span", css: styles2.barLabel, children: [
64960
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.barDot, "aria-hidden": true }),
64961
+ m2.preview()
64962
+ ] }),
64963
+ /* @__PURE__ */ jsx$1(Box, { css: styles2.devices, role: "group", "aria-label": m2.devices(), "data-publish-devices": "", children: DEVICES.map(({ device: d2, icon: icon3 }) => /* @__PURE__ */ jsxs(
64964
+ chakra.button,
64965
+ {
64966
+ type: "button",
64967
+ css: styles2.device,
64968
+ "data-state": device === d2 ? "on" : "off",
64969
+ "aria-pressed": device === d2,
64970
+ "data-publish-device": d2,
64971
+ onClick: () => setDevice(d2),
64972
+ children: [
64973
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.deviceIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: icon3 }) }),
64974
+ m2.device({ device: d2 })
64975
+ ]
64976
+ },
64977
+ d2
64978
+ )) }),
64979
+ env !== void 0 && /* @__PURE__ */ jsxs(Box, { as: "span", css: styles2.env, "data-publish-env": "", children: [
64980
+ m2.env(),
64981
+ " ·",
64982
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.envName, children: env }),
64983
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.envCaret, "aria-hidden": true, children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faChevronDown }) })
64984
+ ] }),
64985
+ /* @__PURE__ */ jsx$1(
64986
+ chakra.button,
64987
+ {
64988
+ type: "button",
64989
+ css: styles2.exit,
64990
+ disabled: exit === void 0,
64991
+ "data-publish-exit": "",
64992
+ onClick: () => {
64993
+ if (exit !== void 0) queueMicrotask(() => exit());
64994
+ },
64995
+ children: m2.exit()
64996
+ }
64997
+ )
64998
+ ] }),
64999
+ /* @__PURE__ */ jsxs(Box, { css: styles2.body, children: [
65000
+ /* @__PURE__ */ jsx$1(Box, { css: styles2.main, "data-publish-main": "", children: /* @__PURE__ */ jsxs(Box, { css: styles2.frame, style: { maxWidth: `${width2}px` }, "data-publish-frame": device, children: [
65001
+ /* @__PURE__ */ jsxs(Box, { css: styles2.head, children: [
65002
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.eyebrow, children: value.project }),
65003
+ /* @__PURE__ */ jsx$1(Box, { as: "h2", css: styles2.title, children: value.title })
65004
+ ] }),
65005
+ page
65006
+ ] }) }),
65007
+ /* @__PURE__ */ jsxs(Box, { as: "aside", css: styles2.aside, "aria-label": head, "data-publish-aside": "", children: [
65008
+ /* @__PURE__ */ jsxs(Box, { css: styles2.asideHead, children: [
65009
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.asideTitle, "data-publish-head": "", children: head }),
65010
+ /* @__PURE__ */ jsxs(Box, { as: "span", css: styles2.asideSub, "data-publish-versions": "", children: [
65011
+ value.title,
65012
+ " ·",
65013
+ " ",
65014
+ standing === "template" ? m2.templateKind() : standing === "current" ? `${liveVersion} ${m2.liveVersion()}` : live === void 0 ? /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.asideVersion, children: nextVersion }) : /* @__PURE__ */ jsxs(Fragment, { children: [
65015
+ liveVersion,
65016
+ " → ",
65017
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.asideVersion, children: nextVersion })
65018
+ ] })
65019
+ ] })
65020
+ ] }),
65021
+ /* @__PURE__ */ jsxs(Box, { css: styles2.asideBody, children: [
65022
+ standing !== "template" && /* @__PURE__ */ jsxs(Fragment, { children: [
65023
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.listHead, "data-publish-count": "", children: listHead }),
65024
+ count > 0 && /* @__PURE__ */ jsx$1(Box, { as: "ul", css: styles2.list, "aria-label": listHead, "data-publish-changes": "", children: changes.map((row, i) => {
65025
+ const kind = row.change.type;
65026
+ return /* @__PURE__ */ jsxs(Box, { as: "li", css: styles2.change, "data-publish-change": kind, children: [
65027
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.sign, "data-sign": kind, "aria-hidden": true, children: kind === "added" ? "+" : kind === "removed" ? "−" : "±" }),
65028
+ /* @__PURE__ */ jsxs(Box, { css: styles2.changeText, children: [
65029
+ /* @__PURE__ */ jsxs(Box, { as: "span", css: styles2.changeLine, children: [
65030
+ m2.changeVerb({ change: kind }),
65031
+ " ",
65032
+ /* @__PURE__ */ jsx$1(Box, { as: "strong", css: styles2.changeName, children: row.name })
65033
+ ] }),
65034
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.changeDetail, children: row.change.value.detail })
65035
+ ] })
65036
+ ] }, `${row.change.value.cell}-${kind}-${i}`);
65037
+ }) }),
65038
+ standing === "ready" && live !== void 0 && /* @__PURE__ */ jsxs(
65039
+ Box,
65040
+ {
65041
+ css: styles2.banner,
65042
+ layerStyle: tone === "change" ? "banner.change" : "banner.guard",
65043
+ "data-tone": tone,
65044
+ role: tone === "warning" ? "alert" : "status",
65045
+ "data-publish-banner": tone,
65046
+ children: [
65047
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.bannerGlyph, "aria-hidden": true, children: tone === "change" ? "△" : "!" }),
65048
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.bannerText, children: tone === "change" ? m2.logicUnchanged() : m2.logicChangedIn({ version: liveVersion, components: changed }) })
65049
+ ]
65050
+ }
65051
+ )
65052
+ ] }),
65053
+ (audience !== void 0 || rollout !== void 0) && /* @__PURE__ */ jsxs(Box, { css: styles2.facts, "data-publish-facts": "", children: [
65054
+ audience !== void 0 && /* @__PURE__ */ jsxs(Box, { css: styles2.fact, children: [
65055
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.factLabel, children: m2.audience() }),
65056
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.factValue, children: audience })
65057
+ ] }),
65058
+ rollout !== void 0 && /* @__PURE__ */ jsxs(Box, { css: styles2.fact, children: [
65059
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.factLabel, children: m2.rollout() }),
65060
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.factValue, children: rollout })
65061
+ ] })
65062
+ ] }),
65063
+ phase.kind === "refused" && /* @__PURE__ */ jsx$1(Box, { as: "span", role: "alert", css: styles2.refusal, "data-publish-refused": "", children: phase.reason })
65064
+ ] }),
65065
+ /* @__PURE__ */ jsxs(Box, { css: styles2.foot, "data-publish-foot": "", children: [
65066
+ /* @__PURE__ */ jsx$1(
65067
+ Button,
65068
+ {
65069
+ type: "button",
65070
+ variant: "outline",
65071
+ size: "sm",
65072
+ "data-publish-save": "",
65073
+ disabled: !summary.unsaved || busy,
65074
+ loading: phase.kind === "applying" && !phase.publish,
65075
+ onClick: () => ask("save"),
65076
+ children: m2.saveAsDraft()
65077
+ }
65078
+ ),
65079
+ /* @__PURE__ */ jsx$1(
65080
+ Button,
65081
+ {
65082
+ type: "button",
65083
+ size: "sm",
65084
+ colorPalette: "brand",
65085
+ "data-publish-publish": "",
65086
+ disabled: standing !== "ready" || busy,
65087
+ loading: phase.kind === "applying" && phase.publish || phase.kind === "publishing",
65088
+ onClick: () => {
65089
+ if (summary.unsaved) ask("publish");
65090
+ else void publish();
65091
+ },
65092
+ children: m2.publishTo({ version: standing === "template" ? void 0 : nextVersion, env })
65093
+ }
65094
+ )
65095
+ ] })
65096
+ ] })
65097
+ ] })
65098
+ ] });
65099
+ });
65100
+ function NamePopover({
65101
+ open,
65102
+ onOpenChange,
65103
+ trigger,
65104
+ label,
65105
+ placeholder,
65106
+ initial: initial2,
65107
+ taken,
65108
+ missing,
65109
+ confirm,
65110
+ children: children2,
65111
+ onConfirm
65112
+ }) {
65113
+ const edit = useSlotRecipe({ key: "sliceEdit" })();
65114
+ const input = useRecipe({ key: "input" })({});
65115
+ const m2 = useStudioMessages();
65116
+ const id3 = useId();
65117
+ const [name, setName] = useState(initial2);
65118
+ const [refused, setRefused] = useState(void 0);
65119
+ const [busy, setBusy] = useState(false);
65120
+ const [wasOpen, setWasOpen] = useState(open);
65121
+ if (open !== wasOpen) {
65122
+ setWasOpen(open);
65123
+ if (open) {
65124
+ setName(initial2);
65125
+ setRefused(void 0);
65126
+ setBusy(false);
65127
+ }
65128
+ }
65129
+ const trimmed = name.trim();
65130
+ const isTaken = trimmed !== "" && taken.has(trimmed);
65131
+ const submit = async () => {
65132
+ if (trimmed === "" || isTaken || busy) return;
65133
+ setBusy(true);
65134
+ setRefused(void 0);
65135
+ try {
65136
+ const why = await onConfirm(trimmed);
65137
+ if (why === void 0) onOpenChange(false);
65138
+ else setRefused(why);
65139
+ } catch (err) {
65140
+ setRefused(err instanceof Error ? err.message : String(err));
65141
+ } finally {
65142
+ setBusy(false);
65143
+ }
65144
+ };
65145
+ return /* @__PURE__ */ jsx$1(
65146
+ SliceEditPopover,
65147
+ {
65148
+ open,
65149
+ onOpenChange,
65150
+ trigger,
65151
+ label,
65152
+ footActions: /* @__PURE__ */ jsxs(Fragment, { children: [
65153
+ /* @__PURE__ */ jsx$1(Button, { type: "button", variant: "outline", size: "xs", disabled: busy, onClick: () => onOpenChange(false), children: m2.cancel() }),
65154
+ /* @__PURE__ */ jsx$1(
65155
+ Button,
65156
+ {
65157
+ type: "submit",
65158
+ form: `${id3}-form`,
65159
+ variant: "outline",
65160
+ size: "xs",
65161
+ loading: busy,
65162
+ disabled: trimmed === "" || isTaken,
65163
+ children: confirm
65164
+ }
65165
+ )
65166
+ ] }),
65167
+ children: /* @__PURE__ */ jsxs(
65168
+ chakra.form,
65169
+ {
65170
+ id: `${id3}-form`,
65171
+ display: "contents",
65172
+ noValidate: true,
65173
+ onSubmit: (e3) => {
65174
+ e3.preventDefault();
65175
+ void submit();
65176
+ },
65177
+ children: [
65178
+ /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "column", gap: "{spacing.1}", children: [
65179
+ /* @__PURE__ */ jsx$1(
65180
+ chakra.input,
65181
+ {
65182
+ css: input,
65183
+ value: name,
65184
+ placeholder,
65185
+ "aria-label": placeholder,
65186
+ autoComplete: "off",
65187
+ autoFocus: true,
65188
+ "aria-invalid": isTaken ? true : void 0,
65189
+ "aria-describedby": trimmed === "" || isTaken ? `${id3}-hint` : void 0,
65190
+ onChange: (e3) => setName(e3.target.value)
65191
+ }
65192
+ ),
65193
+ trimmed === "" && /* @__PURE__ */ jsx$1(Box, { as: "span", id: `${id3}-hint`, css: edit.hint, children: missing }),
65194
+ isTaken && /* @__PURE__ */ jsx$1(Box, { as: "span", id: `${id3}-hint`, css: edit.hintError, children: m2.nameTaken({ name: trimmed }) })
65195
+ ] }),
65196
+ children2,
65197
+ refused !== void 0 && /* @__PURE__ */ jsx$1(Box, { as: "span", role: "alert", css: edit.hintError, "data-refused": "", children: refused })
65198
+ ]
65199
+ }
65200
+ )
65201
+ }
65202
+ );
65203
+ }
65204
+ const StudioSaveTemplate = memo(function StudioSaveTemplate2({ value }) {
65205
+ const edit = useSlotRecipe({ key: "sliceEdit" })();
65206
+ const m2 = useStudioMessages();
65207
+ const [open, setOpen] = useState(false);
65208
+ const onSave = value.onSave;
65209
+ return /* @__PURE__ */ jsx$1(
65210
+ NamePopover,
65211
+ {
65212
+ open,
65213
+ onOpenChange: (next2) => setOpen(next2 && value.enabled),
65214
+ trigger: /* @__PURE__ */ jsx$1(
65215
+ Button,
65216
+ {
65217
+ variant: "outline",
65218
+ disabled: !value.enabled,
65219
+ "data-studio-save-template": "",
65220
+ ...value.enabled ? {} : { title: m2.templateOpen() },
65221
+ children: m2.saveAsTemplate()
65222
+ }
65223
+ ),
65224
+ label: /* @__PURE__ */ jsxs(Fragment, { children: [
65225
+ m2.saveAsTemplate(),
65226
+ " · ",
65227
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: edit.clauseField, children: value.title })
65228
+ ] }),
65229
+ placeholder: m2.templateName(),
65230
+ initial: m2.templateNameFor({ page: value.title }),
65231
+ taken: value.taken,
65232
+ missing: m2.templateNameMissing(),
65233
+ confirm: m2.saveTemplate(),
65234
+ onConfirm: async (name) => {
65235
+ const refused = await onSave(name);
65236
+ return refused.type === "some" ? refused.value : void 0;
65237
+ }
65238
+ }
65239
+ );
65240
+ });
65241
+ function compileStudio() {
65242
+ return {
65243
+ /** Each listed component's palette card. */
65244
+ paletteCards: East.compile(paletteCards, []),
65245
+ /** A project's pages, as the palette lists them. */
65246
+ palettePages: East.compile(palettePages, []),
65247
+ /** Each listed component's tile on the canvas. */
65248
+ canvasTiles: East.compile(canvasTiles, []),
65249
+ /** The selected placement, as the inspector shows it. */
65250
+ inspectorSelection: East.compile(inspectorSelection, []),
65251
+ /** What the publish preview shows of the open entry. */
65252
+ publishSummary: East.compile(publishSummary, []),
65253
+ /** What refused a publish. */
65254
+ publishRefusal: East.compile(publishRefusal, []),
65255
+ /** The projects the record holds. */
65256
+ libraryProjects: East.compile(libraryProjects, []),
65257
+ /** A project's pages, as the page library draws them. */
65258
+ libraryPages: East.compile(libraryPages, []),
65259
+ /** A project's templates, as the page library draws them. */
65260
+ libraryTemplates: East.compile(libraryTemplates, []),
65261
+ /** What refused a write under a new name. */
65262
+ nameWriteRefusal: East.compile(nameWriteRefusal, []),
65263
+ /** The changes from one layout of a page to another. */
65264
+ changes: East.compile(Studio.changes, []),
65265
+ /** The patch that publishes a page. */
65266
+ publish: East.compile(Studio.publish, []),
65267
+ /** The patch that starts a page. */
65268
+ newPage: East.compile(Studio.newPage, []),
65269
+ /** The patch that saves a page's draft as a template. */
65270
+ saveTemplate: East.compile(Studio.saveTemplate, []),
65271
+ /** The canvas's Apply: a batch of placements, one patch through the record's patch write. */
65272
+ save: East.compileAsync(saveCells, [])
65273
+ };
65274
+ }
65275
+ let compiled;
65276
+ function studioEast() {
65277
+ compiled ?? (compiled = compileStudio());
65278
+ return compiled;
65279
+ }
65280
+ const CellsType = ArrayType(StudioCellType);
65281
+ const encodeCells = encodeBeast2For(CellsType);
65282
+ const decodeCells = decodeBeast2For(CellsType);
65283
+ const encodeCell = encodeBeast2For(StudioCellType);
65284
+ const decodeBatch = decodeBeast2For(Editing.Types.ChangeSet(StudioCellType));
65285
+ const CELL_TYPE = toEastTypeValue(StudioCellType);
65286
+ const CELL_DRAFT_TYPE = toEastTypeValue(EditingDraftFieldType(StudioCellType));
65287
+ const keyEqual = equalFor(StudioKeyType);
65288
+ const printKey = printFor(StudioKeyType);
65289
+ const NOTHING_SELECTED = { selected: none$1, request: none$1 };
65290
+ const EastChakraStudioBuilder = memo(function EastChakraStudioBuilder2({ value, storageKey }) {
65291
+ const styles2 = useSlotRecipe({ key: "studioBuilder" })();
65292
+ const statusRecipe = useSlotRecipe({ key: "status" });
65293
+ const m2 = useStudioMessages();
65294
+ const words = useFormatters();
65295
+ const east = studioEast();
65296
+ const { pages: handle, components: components2, project } = value;
65297
+ const id3 = value.id.type === "some" ? value.id.value : void 0;
65298
+ const keys = useMemo(() => builderKeys(id3), [id3]);
65299
+ const read = useCallback(() => handle.read(), [handle]);
65300
+ const { result } = useTrackedEvaluation(read);
65301
+ const pages = result.ok ? result.value : void 0;
65302
+ const first2 = useMemo(() => {
65303
+ if (pages !== void 0) {
65304
+ for (const [key, entry2] of pages) {
65305
+ if (key.project === project && entry2.type === "page") return key;
65306
+ }
65307
+ }
65308
+ return { project, page: "" };
65309
+ }, [pages, project]);
65310
+ const [open, writeOpen] = useOpenPage(keys.page, first2);
65311
+ const openName = printKey(open);
65312
+ let entry;
65313
+ if (pages !== void 0) {
65314
+ for (const [key, found] of pages) {
65315
+ if (keyEqual(key, open)) {
65316
+ entry = found;
65317
+ break;
65318
+ }
65319
+ }
65320
+ }
65321
+ const [ui, setUi] = useState(NOTHING_SELECTED);
65322
+ const [applying2, setApplying] = useState(variant("idle", null));
65323
+ const [drafted, setDrafted] = useState(void 0);
65324
+ const [previewing, setPreviewing] = useState(false);
65325
+ const shown = useRef(openName);
65326
+ useEffect(() => {
65327
+ if (shown.current === openName) return;
65328
+ shown.current = openName;
65329
+ setUi(NOTHING_SELECTED);
65330
+ }, [openName]);
65331
+ const saved = useMemo(() => entry === void 0 ? [] : entry.type === "page" ? entry.value.draft.cells : entry.value.cells, [entry]);
65332
+ const cells = drafted !== void 0 && drafted.page === openName ? drafted.cells : saved;
65333
+ const liveCells = useMemo(() => entry !== void 0 && entry.type === "page" && entry.value.live.type === "some" ? some(entry.value.live.value.page.cells) : none$1, [entry]);
65334
+ const title = entry === void 0 ? "" : entry.type === "page" ? entry.value.draft.title : entry.value.title;
65335
+ const tiles = useMemo(() => east.canvasTiles(components2), [east, components2]);
65336
+ const componentOf = useRef(/* @__PURE__ */ new Map());
65337
+ const cellView = useCallback((cell) => {
65338
+ componentOf.current.set(cell.key, cell.component);
65339
+ const tile = tiles.get(cell.component);
65340
+ return {
65341
+ key: cell.key,
65342
+ row: cell.row,
65343
+ span: cell.span,
65344
+ height: cell.height,
65345
+ minHeight: none$1,
65346
+ align: cell.align,
65347
+ // A frameless component renders bare; one the surface does not
65348
+ // list is its placeholder, in a tile.
65349
+ frame: tile === void 0 ? true : tile.frame,
65350
+ label: cell.title.type === "some" ? cell.title : tile === void 0 ? none$1 : some(tile.name),
65351
+ icon: tile === void 0 ? none$1 : some(tile.icon),
65352
+ meta: tile === void 0 ? some(cell.component) : some(tile.meta)
65353
+ };
65354
+ }, [tiles]);
65355
+ const snapshot = useMemo(() => encodeCells([...saved]), [saved]);
65356
+ const editing = useMemo(() => ({
65357
+ sourceId: `studio.page:${openName}`,
65358
+ entryType: CELL_TYPE,
65359
+ idField: some("key"),
65360
+ draftType: CELL_DRAFT_TYPE,
65361
+ children: none$1,
65362
+ keyType: none$1,
65363
+ snapshot: some(snapshot),
65364
+ readEntry: (entryId) => {
65365
+ const cell = saved.find((c2) => c2.key === entryId);
65366
+ return cell === void 0 ? none$1 : some(encodeCell(cell));
65367
+ },
65368
+ onPatch: none$1,
65369
+ // Apply: the batch, one patch on the page through the record's patch write.
65370
+ onApply: some(variant("async", (bytes) => east.save(handle, open, decodeBatch(bytes)))),
65371
+ mode: variant("batch", null),
65372
+ fields: { key: "key", row: "row", span: "span", height: some("height"), align: some("align") },
65373
+ derive: (bytes) => decodeCells(bytes).map(cellView),
65374
+ // A component dropped from the palette: a placement at its span,
65375
+ // storing its fingerprint; the canvas fits the span to the row.
65376
+ create: some((card, at) => {
65377
+ const component2 = components2.find((c2) => c2.key === card.key);
65378
+ if (component2 === void 0) throw new Error(`No component "${card.key}" is listed`);
65379
+ return encodeCell({
65380
+ key: at.key,
65381
+ row: at.row,
65382
+ span: component2.span,
65383
+ height: none$1,
65384
+ align: variant("top", null),
65385
+ title: none$1,
65386
+ component: component2.key,
65387
+ fingerprint: component2.fingerprint
65388
+ });
65389
+ }),
65390
+ ready: none$1,
65391
+ // The rows the canvas draws, for the palette's counts, the inspector and the preview.
65392
+ onDrafted: some((bytes) => {
65393
+ setDrafted({ page: openName, cells: decodeCells(bytes) });
65394
+ return null;
65395
+ })
65396
+ }), [openName, snapshot, saved, east, handle, open, cellView, components2]);
65397
+ const uiBind = useMemo(() => ({
65398
+ read: () => ui,
65399
+ write: (next2) => {
65400
+ setUi(next2);
65401
+ return null;
65402
+ },
65403
+ has: () => true
65404
+ }), [ui]);
65405
+ const applyBind = useMemo(() => ({
65406
+ read: () => applying2,
65407
+ write: (next2) => {
65408
+ setApplying(next2);
65409
+ return null;
65410
+ },
65411
+ has: () => true
65412
+ }), [applying2]);
65413
+ const canvas = useMemo(() => ({
65414
+ cells: saved.map(cellView),
65415
+ variant: none$1,
65416
+ width: some("1440px"),
65417
+ height: some("fill"),
65418
+ maxHeight: none$1,
65419
+ zoom: none$1,
65420
+ guides: true,
65421
+ editing: some(editing),
65422
+ ui: some(uiBind),
65423
+ view: none$1,
65424
+ apply: some(applyBind),
65425
+ id: none$1,
65426
+ sources: [keys.components],
65427
+ canDrop: none$1,
65428
+ widths: [
65429
+ { label: m2.device({ device: "desktop" }), icon: some("desktop"), width: "1440px" },
65430
+ { label: m2.device({ device: "tablet" }), icon: some("tablet-screen-button"), width: "1024px" }
65431
+ ],
65432
+ toolbar: { start: [], end: [] },
65433
+ panes: { start: none$1, end: none$1 },
65434
+ surface: some(variant("shell", null))
65435
+ }), [saved, cellView, editing, uiBind, applyBind, keys.components, m2]);
65436
+ const listedByKey = useMemo(() => {
65437
+ const byKey = /* @__PURE__ */ new Map();
65438
+ for (const component2 of components2) {
65439
+ const same2 = byKey.get(component2.key);
65440
+ if (same2 === void 0) byKey.set(component2.key, [component2]);
65441
+ else same2.push(component2);
65442
+ }
65443
+ return byKey;
65444
+ }, [components2]);
65445
+ const renderContent = useCallback((cell) => {
65446
+ const component2 = componentOf.current.get(cell.key) ?? "";
65447
+ return /* @__PURE__ */ jsx$1(StudioPlacement, { component: component2, listed: listedByKey.get(component2) ?? [], storageKey: `${storageKey}.canvas.${cell.key}` });
65448
+ }, [listedByKey, storageKey]);
65449
+ const status = entry === void 0 ? void 0 : entry.type === "template" ? { label: m2.statusTemplate(), tone: "neutral", ring: false } : entry.value.live.type === "none" ? { label: m2.statusDraft(), tone: "neutral", ring: true } : east.changes(entry.value.live.value.page, entry.value.draft).length === 0 ? { label: m2.statusLive(), tone: "success", ring: false } : { label: m2.statusLiveEdited(), tone: "warning", ring: false };
65450
+ const statusStyles = status === void 0 ? void 0 : statusRecipe({ status: status.tone, size: "md", ring: status.ring });
65451
+ const taken = useMemo(() => {
65452
+ const names = /* @__PURE__ */ new Set();
65453
+ if (pages !== void 0) {
65454
+ for (const [key] of pages) {
65455
+ if (key.project === open.project) names.add(key.page);
65456
+ }
65457
+ }
65458
+ return names;
65459
+ }, [pages, open.project]);
65460
+ const saveTemplate = useMemo(() => ({
65461
+ title,
65462
+ enabled: entry !== void 0 && entry.type === "page",
65463
+ taken,
65464
+ // The open page, as last saved, as a template under a name — one commit.
65465
+ onSave: async (name) => {
65466
+ const now2 = handle.read();
65467
+ const patch = east.saveTemplate(now2, open, { project: open.project, page: name }, name);
65468
+ const outcome = await handle.commit.patch("", patch);
65469
+ return east.nameWriteRefusal(outcome, name);
65470
+ }
65471
+ }), [title, entry, taken, handle, east, open]);
65472
+ const toolbar = {
65473
+ start: [status !== void 0 && statusStyles !== void 0 && {
65474
+ key: "status",
65475
+ side: "start",
65476
+ version: status.label,
65477
+ forms: [
65478
+ /* @__PURE__ */ jsxs(HStack, { css: statusStyles.root, "data-studio-status": status.tone, children: [
65479
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: statusStyles.indicator }),
65480
+ /* @__PURE__ */ jsx$1(Box, { css: statusStyles.label, children: status.label })
65481
+ ] })
65482
+ ]
65483
+ }],
65484
+ end: [
65485
+ { key: "save-template", side: "end", forms: [/* @__PURE__ */ jsx$1(StudioSaveTemplate, { value: saveTemplate })] },
65486
+ {
65487
+ key: "preview",
65488
+ side: "end",
65489
+ forms: [/* @__PURE__ */ jsx$1(Button, { variant: "outline", "data-studio-preview": "", onClick: () => setPreviewing(true), children: m2.preview() })]
65490
+ },
65491
+ {
65492
+ key: "publish",
65493
+ side: "end",
65494
+ forms: [/* @__PURE__ */ jsx$1(Button, { variant: "outline", "data-studio-open-publish": "", onClick: () => setPreviewing(true), children: m2.publish() })]
65495
+ }
65496
+ ]
65497
+ };
65498
+ const listed = useMemo(() => components2.filter((c2) => !c2.deprecated), [components2]);
65499
+ const cards = useMemo(() => east.paletteCards(listed, [...cells], ui.selected), [east, listed, cells, ui.selected]);
65500
+ const projectPages = useMemo(() => pages === void 0 ? [] : east.palettePages(pages, project), [east, pages, project]);
65501
+ const selectFirst = useCallback((component2) => {
65502
+ const placement = cells.find((c2) => c2.component === component2);
65503
+ if (placement !== void 0) setUi({ selected: some(placement.key), request: none$1 });
65504
+ }, [cells]);
65505
+ const openPage = useCallback((page) => {
65506
+ writeOpen({ project, page });
65507
+ setUi(NOTHING_SELECTED);
65508
+ }, [writeOpen, project]);
65509
+ const paletteIds = useMemo(() => ({ components: keys.components, pages: keys.pages }), [keys.components, keys.pages]);
65510
+ const selection2 = useMemo(
65511
+ () => east.inspectorSelection(components2, [...cells], liveCells, ui.selected),
65512
+ [east, components2, cells, liveCells, ui.selected]
65513
+ );
65514
+ const onRequest = useCallback((request) => {
65515
+ setUi({ selected: some(request.key), request: some(request) });
65516
+ return null;
65517
+ }, []);
65518
+ const inspector = useMemo(() => ({ selection: selection2, onRequest }), [selection2, onRequest]);
65519
+ const selected2 = selection2.type === "some" ? selection2.value : void 0;
65520
+ const summary = useMemo(
65521
+ () => entry === void 0 ? void 0 : east.publishSummary(components2, entry.type === "page" ? entry.value.live : none$1, { title, cells: [...cells] }, [...saved], entry.type === "template"),
65522
+ [east, components2, entry, title, cells, saved]
65523
+ );
65524
+ const preview = useMemo(() => summary === void 0 ? void 0 : {
65525
+ project: open.project,
65526
+ title,
65527
+ summary,
65528
+ env: value.env,
65529
+ audience: value.audience,
65530
+ rollout: value.rollout,
65531
+ apply: applying2,
65532
+ // The canvas applies its drafts, and answers under the id.
65533
+ onApply: (ask) => {
65534
+ setApplying(variant("asked", ask));
65535
+ return null;
65536
+ },
65537
+ // The publish, from the record as it stands when it commits — what an
65538
+ // Apply just before it left.
65539
+ onPublish: async () => {
65540
+ const now2 = handle.read();
65541
+ const patch = east.publish(now2, open, components2);
65542
+ const outcome = await handle.commit.patch("", patch);
65543
+ return east.publishRefusal(outcome);
65544
+ },
65545
+ onExit: some(() => {
65546
+ setPreviewing(false);
65547
+ return null;
65548
+ })
65549
+ }, [summary, open, title, value.env, value.audience, value.rollout, applying2, handle, east, components2]);
65550
+ if (!result.ok) {
65551
+ const message = result.error instanceof Error ? result.error.message : String(result.error);
65552
+ return /* @__PURE__ */ jsx$1(BannerView, { status: "error", title: message });
65553
+ }
65554
+ if (entry === void 0) {
65555
+ return /* @__PURE__ */ jsx$1(
65556
+ EmptyStateView,
65557
+ {
65558
+ icon: { prefix: "fas", name: "file-circle-question" },
65559
+ title: m2.noPageOpen(),
65560
+ description: m2.noPageOpenHint({ project, page: open.page })
65561
+ }
65562
+ );
65563
+ }
65564
+ return /* @__PURE__ */ jsxs(Box, { css: styles2.root, "data-studio-builder": "", children: [
65565
+ /* @__PURE__ */ jsx$1(Box, { css: styles2.canvas, hidden: previewing, "data-studio-canvas": "", children: /* @__PURE__ */ jsx$1(
65566
+ SnapGridEditor,
65567
+ {
65568
+ value: canvas,
65569
+ storageKey: `${storageKey}.canvas`,
65570
+ toolbar,
65571
+ renderContent,
65572
+ panes: {
65573
+ start: /* @__PURE__ */ jsx$1(
65574
+ StudioPalette,
65575
+ {
65576
+ components: listed,
65577
+ cards,
65578
+ pages: projectPages,
65579
+ open: open.project === project ? open.page : "",
65580
+ ids: paletteIds,
65581
+ onSelect: selectFirst,
65582
+ onOpen: openPage,
65583
+ storageKey
65584
+ }
65585
+ ),
65586
+ end: /* @__PURE__ */ jsx$1(
65587
+ DockPane,
65588
+ {
65589
+ storageKey: `${storageKey}.inspector`,
65590
+ icon: "sliders",
65591
+ label: m2.inspector(),
65592
+ badge: selected2 === void 0 ? "" : m2.spanBadge({ span: words.number(Number(selected2.layout.span)) }),
65593
+ active: selected2 !== void 0,
65594
+ detail: selected2 === void 0 ? m2.nothingSelected() : selected2.name,
65595
+ expandedSize: "300px",
65596
+ railSize: "44px",
65597
+ side: "end",
65598
+ surface: "shell",
65599
+ body: /* @__PURE__ */ jsx$1(StudioInspector, { value: inspector })
65600
+ }
65601
+ )
65602
+ }
65603
+ }
65604
+ ) }),
65605
+ previewing && preview !== void 0 && /* @__PURE__ */ jsx$1(
65606
+ StudioPublishPreview,
65607
+ {
65608
+ value: preview,
65609
+ page: /* @__PURE__ */ jsx$1(StudioLayout, { cells, components: components2, storageKey: `${storageKey}.preview` })
65610
+ }
65611
+ )
65612
+ ] });
65613
+ });
65614
+ implementUIComponent(StudioBuilderComponent, EastChakraStudioBuilder);
65615
+ const RANK = { newPage: 0, sort: 1, newPageIcon: 2, searchMid: 3, searchNarrow: 4 };
65616
+ const SORTS = [
65617
+ { key: "az", icon: faArrowDownAZ, name: (m2) => m2.nameAz() },
65618
+ { key: "za", icon: faArrowDownZA, name: (m2) => m2.nameZa() }
65619
+ ];
65620
+ const BLANK = "\0blank";
65621
+ function SortMenu({ sort: sort2, onPick, compact, trigger, caret: caret2, check }) {
65622
+ const m2 = useStudioMessages();
65623
+ const current = SORTS.find((s2) => s2.key === sort2) ?? SORTS[0];
65624
+ const words = m2.sortByName();
65625
+ return /* @__PURE__ */ jsxs(Menu.Root, { positioning: { placement: "bottom-end" }, children: [
65626
+ /* @__PURE__ */ jsx$1(Menu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx$1(
65627
+ chakra.button,
65628
+ {
65629
+ type: "button",
65630
+ css: trigger,
65631
+ "data-page-library-sort": "",
65632
+ ...compact ? { "aria-label": words, title: words } : {},
65633
+ children: compact ? /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: current.icon }) : /* @__PURE__ */ jsxs(Fragment, { children: [
65634
+ words,
65635
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: caret2, "aria-hidden": true, children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faCaretDown }) })
65636
+ ] })
65637
+ }
65638
+ ) }),
65639
+ /* @__PURE__ */ jsx$1(Portal, { children: /* @__PURE__ */ jsx$1(Menu.Positioner, { children: /* @__PURE__ */ jsx$1(Menu.Content, { children: /* @__PURE__ */ jsx$1(Menu.RadioItemGroup, { value: sort2, onValueChange: (d2) => {
65640
+ const picked = SORTS.find((s2) => s2.key === d2.value);
65641
+ if (picked !== void 0 && picked.key !== sort2) onPick(picked.key);
65642
+ }, children: SORTS.map((s2) => /* @__PURE__ */ jsxs(Menu.RadioItem, { value: s2.key, children: [
65643
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: check, children: s2.key === sort2 && /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faCheck }) }),
65644
+ s2.name(m2)
65645
+ ] }, s2.key)) }) }) }) })
65646
+ ] });
65647
+ }
65648
+ const EastChakraStudioLibrary = memo(function EastChakraStudioLibrary2({ value, storageKey }) {
65649
+ const styles2 = useSlotRecipe({ key: "studioLibrary" })();
65650
+ const library2 = useSlotRecipe({ key: "library" })();
65651
+ const edit = useSlotRecipe({ key: "sliceEdit" })();
65652
+ const status = useSlotRecipe({ key: "status" });
65653
+ const liveDot = status({ status: "success" });
65654
+ const draftDot = status({ status: "neutral", ring: true });
65655
+ const button = useRecipe({ key: "button" });
65656
+ const m2 = useStudioMessages();
65657
+ const words = useFormatters();
65658
+ const id3 = useId();
65659
+ const east = studioEast();
65660
+ const { pages: handle, components: components2 } = value;
65661
+ const home = value.project;
65662
+ const keys = useMemo(() => builderKeys(value.id.type === "some" ? value.id.value : void 0), [value.id]);
65663
+ const tellHost = value.onOpen.type === "some" ? value.onOpen.value : void 0;
65664
+ const read = useCallback(() => handle.read(), [handle]);
65665
+ const { result } = useTrackedEvaluation(read);
65666
+ const records = result.ok ? result.value : void 0;
65667
+ const [project, setProject] = useState(home);
65668
+ const [text, setText] = useState("");
65669
+ const [sort2, setSort] = useState("az");
65670
+ const [layout4, setLayout] = useState("grid");
65671
+ const [popover, setPopover] = useState(void 0);
65672
+ const needle = text.toLowerCase();
65673
+ const first2 = useMemo(() => {
65674
+ if (records !== void 0) {
65675
+ for (const [key, entry] of records) {
65676
+ if (key.project === home && entry.type === "page") return key;
65677
+ }
65678
+ }
65679
+ return { project: home, page: "" };
65680
+ }, [records, home]);
65681
+ const [open, writeOpen] = useOpenPage(keys.page, first2);
65682
+ const za = sort2 === "za";
65683
+ const everyPage = useMemo(() => records === void 0 ? [] : east.libraryPages(records, project), [east, records, project]);
65684
+ const everyTemplate = useMemo(
65685
+ () => records === void 0 ? [] : east.libraryTemplates(records, project, components2),
65686
+ [east, records, project, components2]
65687
+ );
65688
+ const pageRows2 = useMemo(() => {
65689
+ const matching2 = everyPage.filter((p2) => p2.title.toLowerCase().includes(needle));
65690
+ return za ? matching2.reverse() : matching2;
65691
+ }, [everyPage, needle, za]);
65692
+ const paneRows = useMemo(() => {
65693
+ const byName = records === void 0 ? [] : east.palettePages(records, project);
65694
+ return za ? [...byName].reverse() : byName;
65695
+ }, [east, records, project, za]);
65696
+ const templateRows = useMemo(() => {
65697
+ const matching2 = everyTemplate.filter((t4) => t4.title.toLowerCase().includes(needle));
65698
+ const ordered = za ? matching2.reverse() : matching2;
65699
+ const blank = { name: "", title: m2.blankGrid(), summary: m2.blankSummary(), cells: [] };
65700
+ return m2.blankGrid().toLowerCase().includes(needle) ? [blank, ...ordered] : ordered;
65701
+ }, [everyTemplate, needle, za, m2]);
65702
+ const projects = useMemo(() => records === void 0 ? [home] : east.libraryProjects(records, home), [east, records, home]);
65703
+ const taken = useMemo(() => {
65704
+ const names = /* @__PURE__ */ new Set();
65705
+ if (records !== void 0) {
65706
+ for (const [key] of records) {
65707
+ if (key.project === project) names.add(key.page);
65708
+ }
65709
+ }
65710
+ return names;
65711
+ }, [records, project]);
65712
+ const openPage = useCallback((name) => {
65713
+ const key = { project, page: name };
65714
+ writeOpen(key);
65715
+ if (tellHost !== void 0) queueMicrotask(() => tellHost(key));
65716
+ }, [project, writeOpen, tellHost]);
65717
+ const startFrom = useCallback((name) => setPopover(name), []);
65718
+ const startBlank = useCallback(() => setPopover(""), []);
65719
+ const wireframes = useMemo(() => {
65720
+ const out = /* @__PURE__ */ new Map();
65721
+ const layouts = [
65722
+ ...templateRows.map((t4) => [`template:${t4.name}`, t4.cells]),
65723
+ ...pageRows2.map((p2) => [`page:${p2.page}`, p2.cells])
65724
+ ];
65725
+ for (const [card, cells] of layouts) {
65726
+ out.set(card, cells.map((c2) => ({
65727
+ key: c2.key,
65728
+ row: c2.row,
65729
+ span: c2.span,
65730
+ height: some(c2.height.type === "some" ? c2.height.value / 12n : 12n),
65731
+ align: c2.align,
65732
+ frame: true
65733
+ })));
65734
+ }
65735
+ return out;
65736
+ }, [templateRows, pageRows2]);
65737
+ const templateMedia = useCallback((item) => /* @__PURE__ */ jsx$1(SnapGridTiles, { wireframe: true, cells: wireframes.get(`template:${item.key}`) ?? [], content: () => null }), [wireframes]);
65738
+ const pageMedia = useCallback((item) => /* @__PURE__ */ jsx$1(SnapGridTiles, { wireframe: true, cells: wireframes.get(`page:${item.key}`) ?? [], content: () => null }), [wireframes]);
65739
+ const templatesGallery = useMemo(() => ({
65740
+ id: `${storageKey}.templates`,
65741
+ hint: none$1,
65742
+ items: templateRows.map((t4) => ({
65743
+ key: t4.name,
65744
+ label: t4.title,
65745
+ sublabel: some(t4.summary),
65746
+ icon: none$1,
65747
+ status: none$1,
65748
+ trailing: none$1,
65749
+ draggable: false,
65750
+ filtered: false,
65751
+ placed: false,
65752
+ media: none$1,
65753
+ avatar: none$1,
65754
+ byline: none$1,
65755
+ action: none$1,
65756
+ search: none$1,
65757
+ groups: /* @__PURE__ */ new Map(),
65758
+ facets: /* @__PURE__ */ new Map(),
65759
+ dims: /* @__PURE__ */ new Map()
65760
+ })),
65761
+ groupOptions: [],
65762
+ groupSummaries: /* @__PURE__ */ new Map(),
65763
+ dimOptions: [],
65764
+ defaultDimensions: [],
65765
+ filterOptions: [],
65766
+ searchable: false,
65767
+ noun: none$1,
65768
+ addLabel: none$1,
65769
+ onAdd: none$1,
65770
+ onCardClick: some((name) => {
65771
+ startFrom(name);
65772
+ return null;
65773
+ }),
65774
+ slice: none$1,
65775
+ style: some({ height: none$1, maxHeight: none$1, virtualization: none$1, columns: some(4n), mediaPlacement: none$1, mediaSize: some("80px") }),
65776
+ variant: some(variant("gallery", null)),
65777
+ layout: none$1,
65778
+ toolbar: false
65779
+ }), [storageKey, templateRows, startFrom]);
65780
+ const pagesGallery = useMemo(() => ({
65781
+ id: `${storageKey}.pages`,
65782
+ hint: none$1,
65783
+ items: pageRows2.map((p2) => ({
65784
+ key: p2.page,
65785
+ label: p2.title,
65786
+ sublabel: some(m2.placements({ n: p2.cells.length, count: words.number(p2.cells.length) })),
65787
+ icon: none$1,
65788
+ status: some(p2.live ? { label: m2.live(), tone: variant("success", null), ring: false } : { label: m2.draft(), tone: variant("neutral", null), ring: true }),
65789
+ trailing: none$1,
65790
+ draggable: false,
65791
+ filtered: false,
65792
+ placed: false,
65793
+ media: none$1,
65794
+ avatar: none$1,
65795
+ byline: none$1,
65796
+ action: some(m2.openInBuilder()),
65797
+ search: none$1,
65798
+ groups: /* @__PURE__ */ new Map(),
65799
+ facets: /* @__PURE__ */ new Map(),
65800
+ dims: /* @__PURE__ */ new Map()
65801
+ })),
65802
+ groupOptions: [],
65803
+ groupSummaries: /* @__PURE__ */ new Map(),
65804
+ dimOptions: [],
65805
+ defaultDimensions: [],
65806
+ filterOptions: [],
65807
+ searchable: false,
65808
+ noun: none$1,
65809
+ addLabel: some(m2.newPageFromTemplate()),
65810
+ onAdd: some(() => {
65811
+ startBlank();
65812
+ return null;
65813
+ }),
65814
+ onCardClick: some((name) => {
65815
+ openPage(name);
65816
+ return null;
65817
+ }),
65818
+ slice: none$1,
65819
+ style: some({ height: none$1, maxHeight: none$1, virtualization: none$1, columns: some(2n), mediaPlacement: some(variant("start", null)), mediaSize: some("156px") }),
65820
+ variant: some(variant("gallery", null)),
65821
+ layout: some(layout4 === "list" ? variant("list", null) : variant("grid", null)),
65822
+ toolbar: false
65823
+ }), [storageKey, pageRows2, m2, words, startBlank, openPage, layout4]);
65824
+ const from2 = popover !== void 0 && popover !== "" ? popover : BLANK;
65825
+ const [template, setTemplate] = useState(from2);
65826
+ const [openedFrom, setOpenedFrom] = useState(popover);
65827
+ if (popover !== openedFrom) {
65828
+ setOpenedFrom(popover);
65829
+ if (popover !== void 0) setTemplate(from2);
65830
+ }
65831
+ const picker = useMemo(() => createListCollection({
65832
+ items: [{ value: BLANK, label: m2.blankGrid() }, ...everyTemplate.map((t4) => ({ value: t4.name, label: t4.title }))]
65833
+ }), [everyTemplate, m2]);
65834
+ const create2 = async (name) => {
65835
+ const now2 = handle.read();
65836
+ const key = { project, page: name };
65837
+ const patch = east.newPage(now2, key, name, template === BLANK ? none$1 : some({ project, page: template }));
65838
+ const outcome = await handle.commit.patch("", patch);
65839
+ const refused = east.nameWriteRefusal(outcome, name);
65840
+ return refused.type === "some" ? refused.value : void 0;
65841
+ };
65842
+ const np = everyPage.length;
65843
+ const nt = everyTemplate.length + 1;
65844
+ const shown = pageRows2.length;
65845
+ const current = open.project === project ? open.page : "";
65846
+ const searchBox = (size3) => /* @__PURE__ */ jsxs(Box, { css: library2.searchBox, "data-size": size3, children: [
65847
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: library2.searchIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faMagnifyingGlass }) }),
65848
+ /* @__PURE__ */ jsx$1(
65849
+ chakra.input,
65850
+ {
65851
+ css: library2.searchInput,
65852
+ placeholder: m2.searchLibrary({ pages: words.number(np), templates: words.number(nt), np, nt }),
65853
+ "aria-label": m2.searchLabel(),
65854
+ value: text,
65855
+ "data-page-library-search": "",
65856
+ onChange: (e3) => setText(e3.target.value),
65857
+ onKeyDown: (e3) => {
65858
+ if (e3.key === "Escape" && text !== "") {
65859
+ e3.preventDefault();
65860
+ setText("");
65861
+ }
65862
+ }
65863
+ }
65864
+ ),
65865
+ text !== "" && /* @__PURE__ */ jsx$1(chakra.button, { type: "button", css: library2.searchClear, "aria-label": m2.clearSearch(), onClick: () => setText(""), children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faXmark }) })
65866
+ ] });
65867
+ const sortMenu = (compact) => /* @__PURE__ */ jsx$1(
65868
+ SortMenu,
65869
+ {
65870
+ sort: sort2,
65871
+ compact,
65872
+ trigger: button({ variant: "outline", size: "sm" }),
65873
+ caret: styles2.caret,
65874
+ check: library2.menuCheck,
65875
+ onPick: setSort
65876
+ }
65877
+ );
65878
+ const newPage = (form) => /* @__PURE__ */ jsx$1(
65879
+ NamePopover,
65880
+ {
65881
+ open: popover !== void 0,
65882
+ onOpenChange: (next2) => setPopover(next2 ? "" : void 0),
65883
+ trigger: /* @__PURE__ */ jsxs(
65884
+ chakra.button,
65885
+ {
65886
+ type: "button",
65887
+ css: button({ variant: "solid", size: "sm" }),
65888
+ colorPalette: "brand",
65889
+ "data-page-library-new": "",
65890
+ ...form !== "full" ? { title: m2.newPageIn({ project }) } : {},
65891
+ ...form === "icon" ? { "aria-label": m2.newPageIn({ project }) } : {},
65892
+ children: [
65893
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.buttonIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faPlus }) }),
65894
+ form === "full" ? m2.newPageIn({ project }) : form === "short" ? m2.newPage() : null
65895
+ ]
65896
+ }
65897
+ ),
65898
+ label: /* @__PURE__ */ jsxs(Fragment, { children: [
65899
+ m2.newPage(),
65900
+ " · ",
65901
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: edit.clauseField, children: project })
65902
+ ] }),
65903
+ placeholder: m2.pageName(),
65904
+ initial: "",
65905
+ taken,
65906
+ missing: m2.pageNameMissing(),
65907
+ confirm: m2.createPage(),
65908
+ onConfirm: create2,
65909
+ children: /* @__PURE__ */ jsxs(Select.Root, { collection: picker, value: [template], onValueChange: (d2) => setTemplate(d2.value[0] ?? BLANK), children: [
65910
+ /* @__PURE__ */ jsx$1(Select.HiddenSelect, {}),
65911
+ /* @__PURE__ */ jsx$1(Select.Label, { children: m2.template() }),
65912
+ /* @__PURE__ */ jsxs(Select.Control, { children: [
65913
+ /* @__PURE__ */ jsx$1(Select.Trigger, { "data-page-library-template": "", children: /* @__PURE__ */ jsx$1(Select.ValueText, {}) }),
65914
+ /* @__PURE__ */ jsx$1(Select.IndicatorGroup, { children: /* @__PURE__ */ jsx$1(Select.Indicator, {}) })
65915
+ ] }),
65916
+ /* @__PURE__ */ jsx$1(Portal, { children: /* @__PURE__ */ jsx$1(Select.Positioner, { children: /* @__PURE__ */ jsx$1(Select.Content, { children: picker.items.map((item) => /* @__PURE__ */ jsxs(Select.Item, { item, children: [
65917
+ item.label,
65918
+ /* @__PURE__ */ jsx$1(Select.ItemIndicator, {})
65919
+ ] }, item.value)) }) }) })
65920
+ ] })
65921
+ }
65922
+ );
65923
+ const toolbarItems = [
65924
+ {
65925
+ key: "search",
65926
+ forms: [searchBox("wide"), searchBox("mid"), searchBox("narrow")],
65927
+ rank: [RANK.searchMid, RANK.searchNarrow]
65928
+ },
65929
+ { key: "sort", side: "end", forms: [sortMenu(false), sortMenu(true)], rank: RANK.sort, version: sort2 },
65930
+ {
65931
+ key: "layout",
65932
+ side: "end",
65933
+ forms: [/* @__PURE__ */ jsx$1(LibraryLayoutSwitch, { layout: layout4, onPick: setLayout })]
65934
+ },
65935
+ { key: "rule", side: "end", forms: [/* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.divider, "aria-hidden": true })] },
65936
+ {
65937
+ key: "new",
65938
+ side: "end",
65939
+ forms: [newPage("full"), newPage("short"), newPage("icon")],
65940
+ rank: [RANK.newPage, RANK.newPageIcon],
65941
+ version: project
65942
+ }
65943
+ ];
65944
+ if (!result.ok) {
65945
+ const message = result.error instanceof Error ? result.error.message : String(result.error);
65946
+ return /* @__PURE__ */ jsx$1(BannerView, { status: "error", title: message });
65947
+ }
65948
+ return /* @__PURE__ */ jsxs(Box, { css: styles2.root, "data-studio-page-library": "", children: [
65949
+ /* @__PURE__ */ jsx$1(Box, { css: styles2.toolbar, "data-slot": "toolbar", children: /* @__PURE__ */ jsx$1(Toolbar, { items: toolbarItems }) }),
65950
+ /* @__PURE__ */ jsxs(Box, { css: styles2.body, children: [
65951
+ /* @__PURE__ */ jsxs(Box, { css: styles2.pane, "data-page-library-pane": "", children: [
65952
+ /* @__PURE__ */ jsxs(Box, { css: styles2.paneSection, role: "group", "aria-labelledby": `${id3}-projects`, children: [
65953
+ /* @__PURE__ */ jsx$1(Box, { css: styles2.paneHead, children: /* @__PURE__ */ jsx$1(Box, { as: "span", id: `${id3}-projects`, css: styles2.paneCaption, children: m2.projects() }) }),
65954
+ projects.map((p2) => {
65955
+ const active = p2 === project;
65956
+ return /* @__PURE__ */ jsxs(
65957
+ chakra.button,
65958
+ {
65959
+ type: "button",
65960
+ css: styles2.paneRow,
65961
+ "data-page-library-project": p2,
65962
+ ...active ? { "data-active": "", "aria-current": "true" } : {},
65963
+ onClick: () => {
65964
+ if (!active) setProject(p2);
65965
+ },
65966
+ children: [
65967
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.paneIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: active ? faFolderOpen : faFolder }) }),
65968
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.paneTitle, children: p2 })
65969
+ ]
65970
+ },
65971
+ p2
65972
+ );
65973
+ })
65974
+ ] }),
65975
+ /* @__PURE__ */ jsx$1(Box, { css: styles2.paneRule, "aria-hidden": true }),
65976
+ /* @__PURE__ */ jsxs(Box, { css: styles2.paneSection, role: "group", "aria-labelledby": `${id3}-pages`, children: [
65977
+ /* @__PURE__ */ jsxs(Box, { css: styles2.paneHead, children: [
65978
+ /* @__PURE__ */ jsx$1(Box, { as: "span", id: `${id3}-pages`, css: styles2.paneCaption, children: m2.pages() }),
65979
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.paneCount, children: words.number(np) })
65980
+ ] }),
65981
+ paneRows.map((p2) => {
65982
+ const dot = p2.live ? liveDot : draftDot;
65983
+ const state = p2.live ? m2.live() : m2.draft();
65984
+ return /* @__PURE__ */ jsxs(
65985
+ chakra.button,
65986
+ {
65987
+ type: "button",
65988
+ css: styles2.paneRow,
65989
+ "data-page": "",
65990
+ "data-page-library-page": p2.page,
65991
+ ...p2.page === current ? { "data-current": "", "aria-current": "page" } : {},
65992
+ onClick: () => openPage(p2.page),
65993
+ children: [
65994
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.paneTitle, children: p2.title }),
65995
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: dot.root, role: "img", "aria-label": state, title: state, children: /* @__PURE__ */ jsx$1(Box, { as: "span", css: dot.indicator }) })
65996
+ ]
65997
+ },
65998
+ p2.page
65999
+ );
66000
+ })
66001
+ ] }),
66002
+ /* @__PURE__ */ jsxs(Box, { css: styles2.legend, "data-page-library-legend": "", children: [
66003
+ /* @__PURE__ */ jsxs(Box, { as: "span", css: liveDot.root, children: [
66004
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: liveDot.indicator }),
66005
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: liveDot.label, children: m2.live() })
66006
+ ] }),
66007
+ /* @__PURE__ */ jsxs(Box, { as: "span", css: draftDot.root, children: [
66008
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: draftDot.indicator }),
66009
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: draftDot.label, children: m2.draft() })
66010
+ ] })
66011
+ ] })
66012
+ ] }),
66013
+ /* @__PURE__ */ jsxs(Box, { css: styles2.main, children: [
66014
+ /* @__PURE__ */ jsxs(Box, { as: "section", css: styles2.section, "data-section": "templates", "aria-labelledby": `${id3}-templates`, children: [
66015
+ /* @__PURE__ */ jsxs(Box, { css: styles2.sectionHead, children: [
66016
+ /* @__PURE__ */ jsx$1(Box, { as: "h3", id: `${id3}-templates`, css: styles2.sectionTitle, children: m2.templates() }),
66017
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.sectionSub, children: m2.cloneToStart() })
66018
+ ] }),
66019
+ /* @__PURE__ */ jsx$1(EastChakraLibrary, { value: templatesGallery, storageKey: `${storageKey}.templates`, renderMedia: templateMedia })
66020
+ ] }),
66021
+ /* @__PURE__ */ jsxs(Box, { as: "section", css: styles2.section, "data-section": "pages", "aria-labelledby": `${id3}-rows`, children: [
66022
+ /* @__PURE__ */ jsxs(Box, { css: styles2.sectionHead, children: [
66023
+ /* @__PURE__ */ jsx$1(Box, { as: "h3", id: `${id3}-rows`, css: styles2.sectionTitle, children: m2.pages() }),
66024
+ /* @__PURE__ */ jsx$1(Box, { as: "span", css: styles2.sectionSub, "data-page-library-shown": "", children: m2.pagesIn({ shown: words.number(shown), total: words.number(np), project, narrowed: shown !== np }) })
66025
+ ] }),
66026
+ /* @__PURE__ */ jsx$1(EastChakraLibrary, { value: pagesGallery, storageKey: `${storageKey}.pages`, renderMedia: pageMedia })
66027
+ ] })
66028
+ ] })
66029
+ ] })
66030
+ ] });
66031
+ });
66032
+ implementUIComponent(StudioLibraryComponent, EastChakraStudioLibrary);
64186
66033
  function formatApiError(error3) {
64187
66034
  if (error3 instanceof ApiError && error3.details != null) {
64188
66035
  const details = error3.details;
@@ -66102,6 +67949,9 @@ export {
66102
67949
  EastChakraDiff,
66103
67950
  EastChakraExperiment,
66104
67951
  EastChakraOntology,
67952
+ EastChakraStudioBuilder,
67953
+ EastChakraStudioLibrary,
67954
+ EastChakraStudioPage,
66105
67955
  EastValueViewer,
66106
67956
  ErrorBoundary,
66107
67957
  FuncPlatform,
@@ -66118,6 +67968,7 @@ export {
66118
67968
  RecordRuntime,
66119
67969
  StagedStore,
66120
67970
  StatusDisplay,
67971
+ StudioMessagesProvider,
66121
67972
  TaskPreview,
66122
67973
  UITaskPreview,
66123
67974
  VirtualizedLogViewer,
@@ -66169,6 +68020,7 @@ export {
66169
68020
  realClock,
66170
68021
  recordChannelKey,
66171
68022
  signatureOfFuncHandleType,
68023
+ studioMessages,
66172
68024
  trackDatasetPath,
66173
68025
  useDataflowCancel,
66174
68026
  useDataflowExecute,
@@ -66208,6 +68060,7 @@ export {
66208
68060
  useRepoList,
66209
68061
  useRepoRemove,
66210
68062
  useRepoStatus,
68063
+ useStudioMessages,
66211
68064
  useTaskDetails,
66212
68065
  useTaskExecutionList,
66213
68066
  useTaskGet,