@cardstack/boxel-cli 0.2.0 → 0.3.0-unstable.58
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/bundled-types/base/-private.d.ts +1 -0
- package/bundled-types/base/address.d.ts +17 -0
- package/bundled-types/base/ai-app-generator.d.ts +14 -0
- package/bundled-types/base/amount-with-currency.d.ts +10 -0
- package/bundled-types/base/avif-image-def.d.ts +12 -0
- package/bundled-types/base/avif-meta-extractor.d.ts +4 -0
- package/bundled-types/base/base64-image.d.ts +25 -0
- package/bundled-types/base/big-integer.d.ts +12 -0
- package/bundled-types/base/boolean.d.ts +14 -0
- package/bundled-types/base/brand-functional-palette.d.ts +16 -0
- package/bundled-types/base/brand-guide.d.ts +26 -0
- package/bundled-types/base/brand-logo.d.ts +29 -0
- package/bundled-types/base/card-api.d.ts +513 -0
- package/bundled-types/base/card-serialization.d.ts +47 -0
- package/bundled-types/base/cards-grid.d.ts +10 -0
- package/bundled-types/base/code-ref.d.ts +14 -0
- package/bundled-types/base/codemirror-editor.d.ts +135 -0
- package/bundled-types/base/color-field/components/advanced-color-picker.d.ts +66 -0
- package/bundled-types/base/color-field/components/color-picker-field.d.ts +22 -0
- package/bundled-types/base/color-field/components/color-wheel-picker.d.ts +44 -0
- package/bundled-types/base/color-field/components/contrast-checker-addon.d.ts +14 -0
- package/bundled-types/base/color-field/components/recent-colors-addon.d.ts +19 -0
- package/bundled-types/base/color-field/components/slider-picker.d.ts +40 -0
- package/bundled-types/base/color-field/components/swatches-picker.d.ts +5 -0
- package/bundled-types/base/color-field/modifiers/setup-element-modifier.d.ts +10 -0
- package/bundled-types/base/color-field/util/color-field-signature.d.ts +9 -0
- package/bundled-types/base/color-field/util/color-utils.d.ts +96 -0
- package/bundled-types/base/color-field/util/css-color-parsers.d.ts +11 -0
- package/bundled-types/base/color.d.ts +10 -0
- package/bundled-types/base/command.d.ts +593 -0
- package/bundled-types/base/commands/search-card-result.d.ts +36 -0
- package/bundled-types/base/components/age.d.ts +22 -0
- package/bundled-types/base/components/business-days.d.ts +16 -0
- package/bundled-types/base/components/card-list.d.ts +25 -0
- package/bundled-types/base/components/cards-grid-layout.d.ts +58 -0
- package/bundled-types/base/components/countdown.d.ts +31 -0
- package/bundled-types/base/components/expiration-warning.d.ts +24 -0
- package/bundled-types/base/components/time-ago.d.ts +24 -0
- package/bundled-types/base/components/time-slots.d.ts +20 -0
- package/bundled-types/base/components/timeline.d.ts +22 -0
- package/bundled-types/base/contains-many-component.d.ts +7 -0
- package/bundled-types/base/coordinate.d.ts +7 -0
- package/bundled-types/base/country.d.ts +23 -0
- package/bundled-types/base/css-value.d.ts +6 -0
- package/bundled-types/base/csv-file-def.d.ts +29 -0
- package/bundled-types/base/currency.d.ts +16 -0
- package/bundled-types/base/date/day.d.ts +9 -0
- package/bundled-types/base/date/month-day.d.ts +10 -0
- package/bundled-types/base/date/month-year.d.ts +9 -0
- package/bundled-types/base/date/month.d.ts +9 -0
- package/bundled-types/base/date/quarter.d.ts +10 -0
- package/bundled-types/base/date/week.d.ts +9 -0
- package/bundled-types/base/date/year.d.ts +9 -0
- package/bundled-types/base/date-range-field.d.ts +12 -0
- package/bundled-types/base/date.d.ts +12 -0
- package/bundled-types/base/datetime-stamp.d.ts +7 -0
- package/bundled-types/base/datetime.d.ts +12 -0
- package/bundled-types/base/default-templates/atom.d.ts +10 -0
- package/bundled-types/base/default-templates/card-info.d.ts +32 -0
- package/bundled-types/base/default-templates/embedded.d.ts +11 -0
- package/bundled-types/base/default-templates/field-edit.d.ts +10 -0
- package/bundled-types/base/default-templates/file-def-edit.d.ts +8 -0
- package/bundled-types/base/default-templates/fitted.d.ts +12 -0
- package/bundled-types/base/default-templates/head.d.ts +13 -0
- package/bundled-types/base/default-templates/image-def-atom.d.ts +8 -0
- package/bundled-types/base/default-templates/image-def-embedded.d.ts +8 -0
- package/bundled-types/base/default-templates/image-def-fitted.d.ts +8 -0
- package/bundled-types/base/default-templates/image-def-isolated.d.ts +8 -0
- package/bundled-types/base/default-templates/isolated-and-edit.d.ts +15 -0
- package/bundled-types/base/default-templates/markdown-fallback.d.ts +19 -0
- package/bundled-types/base/default-templates/markdown.d.ts +60 -0
- package/bundled-types/base/default-templates/missing-template.d.ts +13 -0
- package/bundled-types/base/default-templates/theme-dashboard.d.ts +126 -0
- package/bundled-types/base/detailed-style-reference.d.ts +48 -0
- package/bundled-types/base/email.d.ts +10 -0
- package/bundled-types/base/enum.d.ts +30 -0
- package/bundled-types/base/ethereum-address.d.ts +13 -0
- package/bundled-types/base/field-component.d.ts +65 -0
- package/bundled-types/base/field-support.d.ts +55 -0
- package/bundled-types/base/file-api.d.ts +2 -0
- package/bundled-types/base/file-menu-items.d.ts +4 -0
- package/bundled-types/base/gif-image-def.d.ts +12 -0
- package/bundled-types/base/gif-meta-extractor.d.ts +4 -0
- package/bundled-types/base/gts-file-def.d.ts +7 -0
- package/bundled-types/base/helpers/country.d.ts +3198 -0
- package/bundled-types/base/helpers/sanitized-html.d.ts +2 -0
- package/bundled-types/base/helpers/set-background-image.d.ts +2 -0
- package/bundled-types/base/image-file-def.d.ts +1 -0
- package/bundled-types/base/image.d.ts +8 -0
- package/bundled-types/base/index.d.ts +1 -0
- package/bundled-types/base/join-the-community.d.ts +14 -0
- package/bundled-types/base/jpg-image-def.d.ts +12 -0
- package/bundled-types/base/jpg-meta-extractor.d.ts +4 -0
- package/bundled-types/base/json-file-def.d.ts +23 -0
- package/bundled-types/base/links-to-editor.d.ts +22 -0
- package/bundled-types/base/links-to-many-component.d.ts +7 -0
- package/bundled-types/base/llm-model.d.ts +6 -0
- package/bundled-types/base/markdown-file-def.d.ts +25 -0
- package/bundled-types/base/markdown-helpers.d.ts +26 -0
- package/bundled-types/base/markdown.d.ts +1 -0
- package/bundled-types/base/matrix-event.d.ts +400 -0
- package/bundled-types/base/menu-items.d.ts +21 -0
- package/bundled-types/base/number/components/badge-counter.d.ts +32 -0
- package/bundled-types/base/number/components/badge-metric.d.ts +34 -0
- package/bundled-types/base/number/components/badge-notification.d.ts +38 -0
- package/bundled-types/base/number/components/gauge.d.ts +45 -0
- package/bundled-types/base/number/components/number-input.d.ts +27 -0
- package/bundled-types/base/number/components/progress-bar.d.ts +44 -0
- package/bundled-types/base/number/components/progress-circle.d.ts +41 -0
- package/bundled-types/base/number/components/score.d.ts +41 -0
- package/bundled-types/base/number/components/stat.d.ts +38 -0
- package/bundled-types/base/number/util/index.d.ts +29 -0
- package/bundled-types/base/number.d.ts +52 -0
- package/bundled-types/base/percentage.d.ts +9 -0
- package/bundled-types/base/phone-number.d.ts +25 -0
- package/bundled-types/base/png-image-def.d.ts +12 -0
- package/bundled-types/base/png-meta-extractor.d.ts +4 -0
- package/bundled-types/base/positioned-card.d.ts +7 -0
- package/bundled-types/base/query-field-support.d.ts +6 -0
- package/bundled-types/base/realm-config.d.ts +16 -0
- package/bundled-types/base/realm.d.ts +7 -0
- package/bundled-types/base/resources/command-data.d.ts +43 -0
- package/bundled-types/base/response-field.d.ts +6 -0
- package/bundled-types/base/rich-markdown.d.ts +30 -0
- package/bundled-types/base/shared-state.d.ts +1 -0
- package/bundled-types/base/skill-plus.d.ts +79 -0
- package/bundled-types/base/skill-reference.d.ts +12 -0
- package/bundled-types/base/skill-set.d.ts +18 -0
- package/bundled-types/base/skill.d.ts +21 -0
- package/bundled-types/base/spec.d.ts +108 -0
- package/bundled-types/base/string.d.ts +2 -0
- package/bundled-types/base/structured-theme-variables.d.ts +85 -0
- package/bundled-types/base/structured-theme.d.ts +32 -0
- package/bundled-types/base/style-reference.d.ts +14 -0
- package/bundled-types/base/svg-image-def.d.ts +12 -0
- package/bundled-types/base/svg-meta-extractor.d.ts +12 -0
- package/bundled-types/base/system-card.d.ts +17 -0
- package/bundled-types/base/tag.d.ts +15 -0
- package/bundled-types/base/text-area.d.ts +2 -0
- package/bundled-types/base/text-file-def.d.ts +23 -0
- package/bundled-types/base/text-input-validator.d.ts +13 -0
- package/bundled-types/base/theme.d.ts +2 -0
- package/bundled-types/base/time/duration.d.ts +14 -0
- package/bundled-types/base/time/relative-time.d.ts +10 -0
- package/bundled-types/base/time/time-range.d.ts +11 -0
- package/bundled-types/base/time.d.ts +9 -0
- package/bundled-types/base/ts-file-def.d.ts +26 -0
- package/bundled-types/base/ts-highlight.d.ts +1 -0
- package/bundled-types/base/types/@cardstack/boxel-host/index.d.ts +5 -0
- package/bundled-types/base/types/ember-css-url/index.d.ts +15 -0
- package/bundled-types/base/typography.d.ts +14 -0
- package/bundled-types/base/url.d.ts +13 -0
- package/bundled-types/base/watched-array.d.ts +7 -0
- package/bundled-types/base/webp-image-def.d.ts +12 -0
- package/bundled-types/base/webp-meta-extractor.d.ts +4 -0
- package/bundled-types/base/website.d.ts +8 -0
- package/bundled-types/base/welcome-to-boxel.d.ts +22 -0
- package/bundled-types/boxel-ui/components/accordion/index.gts +50 -0
- package/bundled-types/boxel-ui/components/accordion/item/index.gts +156 -0
- package/bundled-types/boxel-ui/components/accordion/usage.gts +157 -0
- package/bundled-types/boxel-ui/components/add-button/index.gts +46 -0
- package/bundled-types/boxel-ui/components/add-button/usage.gts +54 -0
- package/bundled-types/boxel-ui/components/alert/index.gts +151 -0
- package/bundled-types/boxel-ui/components/alert/usage.gts +66 -0
- package/bundled-types/boxel-ui/components/avatar/index.gts +79 -0
- package/bundled-types/boxel-ui/components/avatar/usage.gts +96 -0
- package/bundled-types/boxel-ui/components/basic-fitted/index.gts +340 -0
- package/bundled-types/boxel-ui/components/basic-fitted/usage.gts +223 -0
- package/bundled-types/boxel-ui/components/button/index.gts +416 -0
- package/bundled-types/boxel-ui/components/button/usage.gts +334 -0
- package/bundled-types/boxel-ui/components/card-container/index.gts +251 -0
- package/bundled-types/boxel-ui/components/card-container/usage.gts +53 -0
- package/bundled-types/boxel-ui/components/card-header/index.gts +473 -0
- package/bundled-types/boxel-ui/components/card-header/usage.gts +295 -0
- package/bundled-types/boxel-ui/components/circle-spinner/index.gts +42 -0
- package/bundled-types/boxel-ui/components/circle-spinner/usage.gts +48 -0
- package/bundled-types/boxel-ui/components/color-palette/index.gts +134 -0
- package/bundled-types/boxel-ui/components/color-palette/usage.gts +69 -0
- package/bundled-types/boxel-ui/components/color-picker/index.gts +125 -0
- package/bundled-types/boxel-ui/components/color-picker/usage.gts +56 -0
- package/bundled-types/boxel-ui/components/container/index.gts +67 -0
- package/bundled-types/boxel-ui/components/container/usage.gts +59 -0
- package/bundled-types/boxel-ui/components/context-button/index.gts +184 -0
- package/bundled-types/boxel-ui/components/context-button/usage.gts +125 -0
- package/bundled-types/boxel-ui/components/copy-button/index.gts +79 -0
- package/bundled-types/boxel-ui/components/copy-button/usage.gts +25 -0
- package/bundled-types/boxel-ui/components/date-range-picker/index.gts +211 -0
- package/bundled-types/boxel-ui/components/date-range-picker/setup.gts +11 -0
- package/bundled-types/boxel-ui/components/date-range-picker/usage.gts +52 -0
- package/bundled-types/boxel-ui/components/drag-and-drop/index.gts +256 -0
- package/bundled-types/boxel-ui/components/drag-and-drop/usage.gts +142 -0
- package/bundled-types/boxel-ui/components/dropdown/index.gts +478 -0
- package/bundled-types/boxel-ui/components/dropdown/trigger/index.gts +70 -0
- package/bundled-types/boxel-ui/components/dropdown/trigger/usage.gts +54 -0
- package/bundled-types/boxel-ui/components/dropdown/usage.gts +119 -0
- package/bundled-types/boxel-ui/components/email-input/index.gts +111 -0
- package/bundled-types/boxel-ui/components/email-input/usage.gts +75 -0
- package/bundled-types/boxel-ui/components/entity-icon-display/index.gts +144 -0
- package/bundled-types/boxel-ui/components/entity-icon-display/usage.gts +54 -0
- package/bundled-types/boxel-ui/components/entity-thumbnail-display/index.gts +148 -0
- package/bundled-types/boxel-ui/components/entity-thumbnail-display/usage.gts +76 -0
- package/bundled-types/boxel-ui/components/field-container/index.gts +150 -0
- package/bundled-types/boxel-ui/components/field-container/usage.gts +188 -0
- package/bundled-types/boxel-ui/components/filter-list/index.gts +255 -0
- package/bundled-types/boxel-ui/components/filter-list/usage.gts +153 -0
- package/bundled-types/boxel-ui/components/fitted-card-container/index.gts +66 -0
- package/bundled-types/boxel-ui/components/fitted-card-container/usage.gts +81 -0
- package/bundled-types/boxel-ui/components/grid-container/grid-item-container/index.gts +37 -0
- package/bundled-types/boxel-ui/components/grid-container/index.gts +116 -0
- package/bundled-types/boxel-ui/components/grid-container/usage.gts +105 -0
- package/bundled-types/boxel-ui/components/header/index.gts +101 -0
- package/bundled-types/boxel-ui/components/header/usage.gts +116 -0
- package/bundled-types/boxel-ui/components/icon-button/index.gts +148 -0
- package/bundled-types/boxel-ui/components/icon-button/usage.gts +249 -0
- package/bundled-types/boxel-ui/components/input/index.gts +560 -0
- package/bundled-types/boxel-ui/components/input/usage.gts +449 -0
- package/bundled-types/boxel-ui/components/input-group/accessories/index.gts +191 -0
- package/bundled-types/boxel-ui/components/input-group/controls/index.gts +54 -0
- package/bundled-types/boxel-ui/components/input-group/index.gts +347 -0
- package/bundled-types/boxel-ui/components/input-group/usage.gts +437 -0
- package/bundled-types/boxel-ui/components/kanban/card.gts +89 -0
- package/bundled-types/boxel-ui/components/kanban/column-header.gts +151 -0
- package/bundled-types/boxel-ui/components/kanban/drag.gts +1007 -0
- package/bundled-types/boxel-ui/components/kanban/engine.ts +247 -0
- package/bundled-types/boxel-ui/components/kanban/ghost.gts +64 -0
- package/bundled-types/boxel-ui/components/kanban/index.gts +16 -0
- package/bundled-types/boxel-ui/components/kanban/modifiers.gts +42 -0
- package/bundled-types/boxel-ui/components/kanban/plane-inner.gts +525 -0
- package/bundled-types/boxel-ui/components/kanban/plane.gts +163 -0
- package/bundled-types/boxel-ui/components/kanban/usage.gts +392 -0
- package/bundled-types/boxel-ui/components/label/index.gts +64 -0
- package/bundled-types/boxel-ui/components/loading-indicator/index.gts +78 -0
- package/bundled-types/boxel-ui/components/loading-indicator/usage.gts +72 -0
- package/bundled-types/boxel-ui/components/menu/index.gts +267 -0
- package/bundled-types/boxel-ui/components/menu/usage.gts +100 -0
- package/bundled-types/boxel-ui/components/message/index.gts +146 -0
- package/bundled-types/boxel-ui/components/message/usage.gts +263 -0
- package/bundled-types/boxel-ui/components/modal/index.gts +159 -0
- package/bundled-types/boxel-ui/components/modal/usage.gts +206 -0
- package/bundled-types/boxel-ui/components/multi-select/after-options.gts +59 -0
- package/bundled-types/boxel-ui/components/multi-select/index.gts +230 -0
- package/bundled-types/boxel-ui/components/multi-select/selected-item.gts +91 -0
- package/bundled-types/boxel-ui/components/multi-select/trigger.gts +190 -0
- package/bundled-types/boxel-ui/components/multi-select/usage.gts +420 -0
- package/bundled-types/boxel-ui/components/phone-input/index.gts +149 -0
- package/bundled-types/boxel-ui/components/phone-input/usage.gts +73 -0
- package/bundled-types/boxel-ui/components/picker/before-options-with-search.gts +340 -0
- package/bundled-types/boxel-ui/components/picker/index.gts +427 -0
- package/bundled-types/boxel-ui/components/picker/option-row.gts +270 -0
- package/bundled-types/boxel-ui/components/picker/selected-item.gts +171 -0
- package/bundled-types/boxel-ui/components/picker/trigger-labeled.gts +216 -0
- package/bundled-types/boxel-ui/components/picker/usage.gts +179 -0
- package/bundled-types/boxel-ui/components/pill/index.gts +231 -0
- package/bundled-types/boxel-ui/components/pill/usage.gts +230 -0
- package/bundled-types/boxel-ui/components/progress-bar/index.gts +124 -0
- package/bundled-types/boxel-ui/components/progress-bar/usage.gts +131 -0
- package/bundled-types/boxel-ui/components/progress-radial/index.gts +95 -0
- package/bundled-types/boxel-ui/components/progress-radial/usage.gts +79 -0
- package/bundled-types/boxel-ui/components/radio-input/index.gts +143 -0
- package/bundled-types/boxel-ui/components/radio-input/item.gts +210 -0
- package/bundled-types/boxel-ui/components/radio-input/usage.gts +303 -0
- package/bundled-types/boxel-ui/components/realm-icon/index.gts +129 -0
- package/bundled-types/boxel-ui/components/realm-icon/usage.gts +62 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/handle.gts +180 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/index.gts +341 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/panel.gts +86 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/usage.gts +350 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/adjust-layout-by-delta.ts +231 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/assert.ts +10 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/calculate-delta-percentage.ts +41 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/calculate-unsafe-default-layout.ts +53 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/compare-layouts.ts +12 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/const.ts +6 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/determine-pivot-indices.ts +15 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-panel-element.ts +10 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-panel-elements-for-group.ts +8 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-panel-group-element.ts +21 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-resize-handle-element-index.ts +14 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-resize-handle-element.ts +12 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/dom/get-resize-handle-elements-for-group.ts +10 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/fuzzy-layouts-equal.ts +22 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/fuzzy-numbers.ts +21 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/get-resize-event-coordinates.ts +8 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/get-resize-event-cursor-position.ts +10 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/panel-resize-handle-registry.ts +446 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/resize-panel.ts +35 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/types.ts +23 -0
- package/bundled-types/boxel-ui/components/resizable-panel-group/utils/validate-panel-group-layout.ts +86 -0
- package/bundled-types/boxel-ui/components/select/index.gts +882 -0
- package/bundled-types/boxel-ui/components/select/trigger.gts +132 -0
- package/bundled-types/boxel-ui/components/select/usage.gts +353 -0
- package/bundled-types/boxel-ui/components/skeleton-placeholder/index.gts +89 -0
- package/bundled-types/boxel-ui/components/skeleton-placeholder/usage.gts +102 -0
- package/bundled-types/boxel-ui/components/sort-dropdown/index.gts +91 -0
- package/bundled-types/boxel-ui/components/sort-dropdown/usage.gts +77 -0
- package/bundled-types/boxel-ui/components/swatch/index.gts +81 -0
- package/bundled-types/boxel-ui/components/swatch/usage.gts +57 -0
- package/bundled-types/boxel-ui/components/switch/index.gts +95 -0
- package/bundled-types/boxel-ui/components/switch/usage.gts +79 -0
- package/bundled-types/boxel-ui/components/tabbed-header/index.gts +141 -0
- package/bundled-types/boxel-ui/components/tabbed-header/usage.gts +103 -0
- package/bundled-types/boxel-ui/components/tag/index.gts +50 -0
- package/bundled-types/boxel-ui/components/tag/usage.gts +89 -0
- package/bundled-types/boxel-ui/components/tag-list/index.gts +85 -0
- package/bundled-types/boxel-ui/components/tag-list/usage.gts +129 -0
- package/bundled-types/boxel-ui/components/tooltip/index.gts +306 -0
- package/bundled-types/boxel-ui/components/tooltip/usage.gts +168 -0
- package/bundled-types/boxel-ui/components/view-selector/index.gts +166 -0
- package/bundled-types/boxel-ui/components/view-selector/usage.gts +149 -0
- package/bundled-types/boxel-ui/components.ts +169 -0
- package/bundled-types/boxel-ui/helpers/add-class-to-svg.ts +8 -0
- package/bundled-types/boxel-ui/helpers/clipboard.ts +21 -0
- package/bundled-types/boxel-ui/helpers/cn.ts +12 -0
- package/bundled-types/boxel-ui/helpers/color-tools.ts +331 -0
- package/bundled-types/boxel-ui/helpers/compact.ts +3 -0
- package/bundled-types/boxel-ui/helpers/contrast-color.ts +32 -0
- package/bundled-types/boxel-ui/helpers/css-var.ts +41 -0
- package/bundled-types/boxel-ui/helpers/currency-format.ts +25 -0
- package/bundled-types/boxel-ui/helpers/dayjs-format.ts +27 -0
- package/bundled-types/boxel-ui/helpers/deterministic-color-from-string.ts +45 -0
- package/bundled-types/boxel-ui/helpers/element.ts +16 -0
- package/bundled-types/boxel-ui/helpers/extract-css-variables.ts +126 -0
- package/bundled-types/boxel-ui/helpers/format-age.ts +72 -0
- package/bundled-types/boxel-ui/helpers/format-countdown.ts +110 -0
- package/bundled-types/boxel-ui/helpers/format-currency.ts +95 -0
- package/bundled-types/boxel-ui/helpers/format-date-time.ts +567 -0
- package/bundled-types/boxel-ui/helpers/format-duration.ts +143 -0
- package/bundled-types/boxel-ui/helpers/format-file-size.ts +49 -0
- package/bundled-types/boxel-ui/helpers/format-list.ts +73 -0
- package/bundled-types/boxel-ui/helpers/format-names.ts +103 -0
- package/bundled-types/boxel-ui/helpers/format-number.ts +140 -0
- package/bundled-types/boxel-ui/helpers/format-ordinal.ts +115 -0
- package/bundled-types/boxel-ui/helpers/format-period.ts +188 -0
- package/bundled-types/boxel-ui/helpers/format-relative-time.ts +789 -0
- package/bundled-types/boxel-ui/helpers/generate-css-variables.ts +47 -0
- package/bundled-types/boxel-ui/helpers/markdown-escape.ts +36 -0
- package/bundled-types/boxel-ui/helpers/math-helpers.ts +18 -0
- package/bundled-types/boxel-ui/helpers/menu-divider.ts +15 -0
- package/bundled-types/boxel-ui/helpers/menu-item.ts +76 -0
- package/bundled-types/boxel-ui/helpers/optional.ts +7 -0
- package/bundled-types/boxel-ui/helpers/pick.ts +11 -0
- package/bundled-types/boxel-ui/helpers/sanitize-html.ts +45 -0
- package/bundled-types/boxel-ui/helpers/string.ts +15 -0
- package/bundled-types/boxel-ui/helpers/theme-css.ts +148 -0
- package/bundled-types/boxel-ui/helpers/truth-helpers.ts +48 -0
- package/bundled-types/boxel-ui/helpers/validate-email-format.ts +138 -0
- package/bundled-types/boxel-ui/helpers/validate-phone-format.ts +201 -0
- package/bundled-types/boxel-ui/helpers.ts +134 -0
- package/bundled-types/boxel-ui/icons/ai-bw.gts +22 -0
- package/bundled-types/boxel-ui/icons/arrow-left.gts +25 -0
- package/bundled-types/boxel-ui/icons/arrow-right.gts +28 -0
- package/bundled-types/boxel-ui/icons/arrow-top-left.gts +22 -0
- package/bundled-types/boxel-ui/icons/arrow-up.gts +25 -0
- package/bundled-types/boxel-ui/icons/atom.gts +26 -0
- package/bundled-types/boxel-ui/icons/boxel-icon-with-text.gts +29 -0
- package/bundled-types/boxel-ui/icons/boxel-icon.gts +34 -0
- package/bundled-types/boxel-ui/icons/card-definition.gts +26 -0
- package/bundled-types/boxel-ui/icons/card-instance.gts +26 -0
- package/bundled-types/boxel-ui/icons/card.gts +24 -0
- package/bundled-types/boxel-ui/icons/cardbot-lg.gts +24 -0
- package/bundled-types/boxel-ui/icons/caret-down.gts +23 -0
- package/bundled-types/boxel-ui/icons/caret-up.gts +23 -0
- package/bundled-types/boxel-ui/icons/check-mark.gts +23 -0
- package/bundled-types/boxel-ui/icons/chevron-right.gts +23 -0
- package/bundled-types/boxel-ui/icons/copy.gts +28 -0
- package/bundled-types/boxel-ui/icons/diagonal-arrow-left-up.gts +21 -0
- package/bundled-types/boxel-ui/icons/download.gts +19 -0
- package/bundled-types/boxel-ui/icons/dropdown-arrow-down.gts +20 -0
- package/bundled-types/boxel-ui/icons/dropdown-arrow-filled.gts +19 -0
- package/bundled-types/boxel-ui/icons/dropdown-arrow-up.gts +20 -0
- package/bundled-types/boxel-ui/icons/edit.gts +14 -0
- package/bundled-types/boxel-ui/icons/embedded.gts +34 -0
- package/bundled-types/boxel-ui/icons/exclamation-circle.gts +26 -0
- package/bundled-types/boxel-ui/icons/exclamation.gts +20 -0
- package/bundled-types/boxel-ui/icons/eye.gts +19 -0
- package/bundled-types/boxel-ui/icons/failure-bordered.gts +26 -0
- package/bundled-types/boxel-ui/icons/field.gts +26 -0
- package/bundled-types/boxel-ui/icons/file-alert.gts +28 -0
- package/bundled-types/boxel-ui/icons/file.gts +27 -0
- package/bundled-types/boxel-ui/icons/fitted.gts +42 -0
- package/bundled-types/boxel-ui/icons/folder.gts +26 -0
- package/bundled-types/boxel-ui/icons/form.gts +38 -0
- package/bundled-types/boxel-ui/icons/four-lines.gts +21 -0
- package/bundled-types/boxel-ui/icons/grid-3x3.gts +26 -0
- package/bundled-types/boxel-ui/icons/group.gts +22 -0
- package/bundled-types/boxel-ui/icons/head.gts +28 -0
- package/bundled-types/boxel-ui/icons/highlight-icon.gts +46 -0
- package/bundled-types/boxel-ui/icons/icon-circle-selected.gts +25 -0
- package/bundled-types/boxel-ui/icons/icon-circle.gts +25 -0
- package/bundled-types/boxel-ui/icons/icon-code.gts +22 -0
- package/bundled-types/boxel-ui/icons/icon-funnel.gts +23 -0
- package/bundled-types/boxel-ui/icons/icon-globe.gts +19 -0
- package/bundled-types/boxel-ui/icons/icon-grid.gts +68 -0
- package/bundled-types/boxel-ui/icons/icon-hexagon.gts +22 -0
- package/bundled-types/boxel-ui/icons/icon-inherit.gts +19 -0
- package/bundled-types/boxel-ui/icons/icon-link.gts +20 -0
- package/bundled-types/boxel-ui/icons/icon-list.gts +40 -0
- package/bundled-types/boxel-ui/icons/icon-minus-circle.gts +26 -0
- package/bundled-types/boxel-ui/icons/icon-pencil-crossed-out.gts +33 -0
- package/bundled-types/boxel-ui/icons/icon-pencil-not-crossed-out.gts +21 -0
- package/bundled-types/boxel-ui/icons/icon-pencil.gts +23 -0
- package/bundled-types/boxel-ui/icons/icon-plus-circle.gts +31 -0
- package/bundled-types/boxel-ui/icons/icon-plus-thin.gts +19 -0
- package/bundled-types/boxel-ui/icons/icon-plus.gts +20 -0
- package/bundled-types/boxel-ui/icons/icon-search-thick.gts +27 -0
- package/bundled-types/boxel-ui/icons/icon-search.gts +25 -0
- package/bundled-types/boxel-ui/icons/icon-table.gts +44 -0
- package/bundled-types/boxel-ui/icons/icon-trash.gts +24 -0
- package/bundled-types/boxel-ui/icons/icon-turn-down-right.gts +18 -0
- package/bundled-types/boxel-ui/icons/icon-x.gts +21 -0
- package/bundled-types/boxel-ui/icons/image-placeholder.gts +30 -0
- package/bundled-types/boxel-ui/icons/isolated.gts +20 -0
- package/bundled-types/boxel-ui/icons/loading-indicator.gts +26 -0
- package/bundled-types/boxel-ui/icons/lock.gts +23 -0
- package/bundled-types/boxel-ui/icons/markdown.gts +19 -0
- package/bundled-types/boxel-ui/icons/profile.gts +23 -0
- package/bundled-types/boxel-ui/icons/publish-site-icon.gts +25 -0
- package/bundled-types/boxel-ui/icons/rows-4.gts +26 -0
- package/bundled-types/boxel-ui/icons/select-all.gts +25 -0
- package/bundled-types/boxel-ui/icons/send.gts +21 -0
- package/bundled-types/boxel-ui/icons/sparkle.gts +21 -0
- package/bundled-types/boxel-ui/icons/star-filled.gts +25 -0
- package/bundled-types/boxel-ui/icons/star-half-fill.gts +27 -0
- package/bundled-types/boxel-ui/icons/star.gts +25 -0
- package/bundled-types/boxel-ui/icons/success-bordered.gts +30 -0
- package/bundled-types/boxel-ui/icons/three-dots-horizontal.gts +21 -0
- package/bundled-types/boxel-ui/icons/triangle-left.gts +23 -0
- package/bundled-types/boxel-ui/icons/triangle-right.gts +23 -0
- package/bundled-types/boxel-ui/icons/types.ts +10 -0
- package/bundled-types/boxel-ui/icons/upload.gts +20 -0
- package/bundled-types/boxel-ui/icons/warning.gts +19 -0
- package/bundled-types/boxel-ui/icons.gts +246 -0
- package/bundled-types/boxel-ui/modifiers/auto-focus.ts +7 -0
- package/bundled-types/boxel-ui/modifiers/set-css-var.ts +24 -0
- package/bundled-types/boxel-ui/modifiers.ts +14 -0
- package/bundled-types/boxel-ui/types/@cardstack/boxel-ui/index.d.ts +3 -0
- package/bundled-types/boxel-ui/types/ember-css-url/index.d.ts +15 -0
- package/bundled-types/boxel-ui/types/ember-draggable-modifiers/index.d.ts +109 -0
- package/bundled-types/boxel-ui/types/ember-draggable-modifiers/utils.d.ts +7 -0
- package/bundled-types/boxel-ui/types/ember-focus-trap/index.d.ts +20 -0
- package/bundled-types/boxel-ui/types/ember-power-calendar/components/index.d.ts +9 -0
- package/bundled-types/boxel-ui/types/ember-resize-modifier/index.d.ts +14 -0
- package/bundled-types/boxel-ui/types/ember-set-body-class/index.d.ts +12 -0
- package/bundled-types/boxel-ui/types/ember-sortable/index.d.ts +52 -0
- package/bundled-types/boxel-ui/types/global.d.ts +7 -0
- package/bundled-types/boxel-ui/usage.ts +112 -0
- package/bundled-types/boxel-ui/utils/date-utils.ts +192 -0
- package/bundled-types/boxel-ui/utils/fitted-formats.ts +161 -0
- package/bundled-types/host-app/app.ts +22 -0
- package/bundled-types/host-app/commands/add-field-to-card-definition.ts +74 -0
- package/bundled-types/host-app/commands/ai-assistant.ts +203 -0
- package/bundled-types/host-app/commands/apply-markdown-edit.ts +203 -0
- package/bundled-types/host-app/commands/apply-search-replace-block.ts +225 -0
- package/bundled-types/host-app/commands/ask-ai.ts +66 -0
- package/bundled-types/host-app/commands/authed-fetch.ts +53 -0
- package/bundled-types/host-app/commands/bot-requests/create-listing-pr-request.ts +77 -0
- package/bundled-types/host-app/commands/bot-requests/send-bot-trigger-event.ts +53 -0
- package/bundled-types/host-app/commands/can-read-realm.ts +34 -0
- package/bundled-types/host-app/commands/cancel-indexing-job.ts +29 -0
- package/bundled-types/host-app/commands/check-correctness.ts +309 -0
- package/bundled-types/host-app/commands/copy-and-edit.ts +311 -0
- package/bundled-types/host-app/commands/copy-card-as-markdown.ts +41 -0
- package/bundled-types/host-app/commands/copy-card-to-stack.ts +70 -0
- package/bundled-types/host-app/commands/copy-card.ts +67 -0
- package/bundled-types/host-app/commands/copy-file-to-realm.ts +82 -0
- package/bundled-types/host-app/commands/copy-source.ts +46 -0
- package/bundled-types/host-app/commands/create-ai-assistant-room.ts +144 -0
- package/bundled-types/host-app/commands/create-and-open-submission-workflow-card.ts +30 -0
- package/bundled-types/host-app/commands/create-specs.ts +422 -0
- package/bundled-types/host-app/commands/create-submission-workflow.ts +172 -0
- package/bundled-types/host-app/commands/evaluate-module.ts +119 -0
- package/bundled-types/host-app/commands/execute-atomic-operations.ts +44 -0
- package/bundled-types/host-app/commands/fetch-card-json.ts +33 -0
- package/bundled-types/host-app/commands/full-reindex-realm.ts +30 -0
- package/bundled-types/host-app/commands/generate-example-cards.ts +298 -0
- package/bundled-types/host-app/commands/generate-readme-spec.ts +116 -0
- package/bundled-types/host-app/commands/generate-theme-example.ts +147 -0
- package/bundled-types/host-app/commands/generate-thumbnail.ts +247 -0
- package/bundled-types/host-app/commands/get-all-realm-metas.ts +38 -0
- package/bundled-types/host-app/commands/get-available-realm-identifiers.ts +29 -0
- package/bundled-types/host-app/commands/get-card-type-schema.ts +59 -0
- package/bundled-types/host-app/commands/get-card.ts +34 -0
- package/bundled-types/host-app/commands/get-catalog-realm-identifiers.ts +29 -0
- package/bundled-types/host-app/commands/get-default-writable-realm.ts +28 -0
- package/bundled-types/host-app/commands/get-events-from-room.ts +70 -0
- package/bundled-types/host-app/commands/get-realm-of-resource-identifier.ts +37 -0
- package/bundled-types/host-app/commands/get-user-system-card.ts +38 -0
- package/bundled-types/host-app/commands/index.ts +590 -0
- package/bundled-types/host-app/commands/instantiate-card.ts +185 -0
- package/bundled-types/host-app/commands/invalidate-realm-identifiers.ts +33 -0
- package/bundled-types/host-app/commands/invite-user-to-room.ts +34 -0
- package/bundled-types/host-app/commands/lint-and-fix.ts +60 -0
- package/bundled-types/host-app/commands/listing-action-build.ts +79 -0
- package/bundled-types/host-app/commands/listing-action-init.ts +106 -0
- package/bundled-types/host-app/commands/listing-create.ts +632 -0
- package/bundled-types/host-app/commands/listing-generate-example.ts +83 -0
- package/bundled-types/host-app/commands/listing-install.ts +227 -0
- package/bundled-types/host-app/commands/listing-remix.ts +150 -0
- package/bundled-types/host-app/commands/listing-update-specs.ts +116 -0
- package/bundled-types/host-app/commands/listing-use.ts +97 -0
- package/bundled-types/host-app/commands/one-shot-llm-request.ts +209 -0
- package/bundled-types/host-app/commands/open-ai-assistant-room.ts +38 -0
- package/bundled-types/host-app/commands/open-create-listing-modal.ts +52 -0
- package/bundled-types/host-app/commands/open-in-interact-mode.ts +36 -0
- package/bundled-types/host-app/commands/open-workspace.ts +38 -0
- package/bundled-types/host-app/commands/patch-card-instance.ts +108 -0
- package/bundled-types/host-app/commands/patch-code.ts +243 -0
- package/bundled-types/host-app/commands/patch-fields.ts +304 -0
- package/bundled-types/host-app/commands/patch-theme.ts +52 -0
- package/bundled-types/host-app/commands/persist-module-inspector-view.ts +41 -0
- package/bundled-types/host-app/commands/populate-with-sample-data.ts +84 -0
- package/bundled-types/host-app/commands/preview-format.ts +52 -0
- package/bundled-types/host-app/commands/read-binary-file.ts +62 -0
- package/bundled-types/host-app/commands/read-card-for-ai-assistant.ts +50 -0
- package/bundled-types/host-app/commands/read-file-for-ai-assistant.ts +46 -0
- package/bundled-types/host-app/commands/read-source.ts +46 -0
- package/bundled-types/host-app/commands/read-text-file.ts +44 -0
- package/bundled-types/host-app/commands/register-bot.ts +42 -0
- package/bundled-types/host-app/commands/reindex-realm.ts +30 -0
- package/bundled-types/host-app/commands/retry-submission-workflow.ts +119 -0
- package/bundled-types/host-app/commands/sanitize-module-list.ts +83 -0
- package/bundled-types/host-app/commands/save-card.ts +44 -0
- package/bundled-types/host-app/commands/screenshot-card.ts +148 -0
- package/bundled-types/host-app/commands/search-and-choose.ts +180 -0
- package/bundled-types/host-app/commands/search-cards.ts +102 -0
- package/bundled-types/host-app/commands/search-google-images.ts +100 -0
- package/bundled-types/host-app/commands/send-ai-assistant-message.ts +122 -0
- package/bundled-types/host-app/commands/send-request-via-proxy.ts +70 -0
- package/bundled-types/host-app/commands/serialize-card.ts +45 -0
- package/bundled-types/host-app/commands/set-active-llm.ts +39 -0
- package/bundled-types/host-app/commands/set-user-system-card.ts +29 -0
- package/bundled-types/host-app/commands/show-card.ts +102 -0
- package/bundled-types/host-app/commands/show-file.ts +39 -0
- package/bundled-types/host-app/commands/store-add.ts +37 -0
- package/bundled-types/host-app/commands/summarize-session.ts +82 -0
- package/bundled-types/host-app/commands/switch-submode.ts +112 -0
- package/bundled-types/host-app/commands/sync-openrouter-models.ts +373 -0
- package/bundled-types/host-app/commands/transform-cards.ts +59 -0
- package/bundled-types/host-app/commands/unregister-bot.ts +29 -0
- package/bundled-types/host-app/commands/update-code-path-with-selection.ts +45 -0
- package/bundled-types/host-app/commands/update-playground-selection.ts +37 -0
- package/bundled-types/host-app/commands/update-room-skills.ts +231 -0
- package/bundled-types/host-app/commands/utils.ts +178 -0
- package/bundled-types/host-app/commands/validate-realm.ts +40 -0
- package/bundled-types/host-app/commands/write-binary-file.ts +142 -0
- package/bundled-types/host-app/commands/write-text-file.ts +104 -0
- package/bundled-types/host-app/components/.gitkeep +0 -0
- package/bundled-types/host-app/components/ai-assistant/action-bar.gts +188 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-button-active-bg.webp +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-button-active-bg@2x.webp +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-button-active-bg@3x.webp +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-icon-animated.webp +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-icon-bw.png +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-icon-bw@2x.png +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-icon-bw@3x.png +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-icon.webp +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-icon@2x.webp +0 -0
- package/bundled-types/host-app/components/ai-assistant/ai-assist-icon@3x.webp +0 -0
- package/bundled-types/host-app/components/ai-assistant/apply-button/index.gts +226 -0
- package/bundled-types/host-app/components/ai-assistant/apply-button/usage.gts +81 -0
- package/bundled-types/host-app/components/ai-assistant/attached-file-dropdown-menu.gts +179 -0
- package/bundled-types/host-app/components/ai-assistant/attachment-picker/attach-button.gts +176 -0
- package/bundled-types/host-app/components/ai-assistant/attachment-picker/attached-items.gts +271 -0
- package/bundled-types/host-app/components/ai-assistant/attachment-picker/index.gts +144 -0
- package/bundled-types/host-app/components/ai-assistant/attachment-picker/usage.gts +127 -0
- package/bundled-types/host-app/components/ai-assistant/button.gts +60 -0
- package/bundled-types/host-app/components/ai-assistant/chat-input/index.gts +203 -0
- package/bundled-types/host-app/components/ai-assistant/chat-input/usage.gts +68 -0
- package/bundled-types/host-app/components/ai-assistant/code-block/actions.gts +58 -0
- package/bundled-types/host-app/components/ai-assistant/code-block/apply-code-patch-button.gts +66 -0
- package/bundled-types/host-app/components/ai-assistant/code-block/command-header.gts +115 -0
- package/bundled-types/host-app/components/ai-assistant/code-block/diff-editor-header.gts +209 -0
- package/bundled-types/host-app/components/ai-assistant/code-block/index.gts +228 -0
- package/bundled-types/host-app/components/ai-assistant/code-block/patch-footer.gts +32 -0
- package/bundled-types/host-app/components/ai-assistant/code-block/view-code-button.gts +73 -0
- package/bundled-types/host-app/components/ai-assistant/focus-pill/index.gts +60 -0
- package/bundled-types/host-app/components/ai-assistant/focus-pill/usage.gts +45 -0
- package/bundled-types/host-app/components/ai-assistant/llm-mode-toggle.gts +113 -0
- package/bundled-types/host-app/components/ai-assistant/llm-select.gts +158 -0
- package/bundled-types/host-app/components/ai-assistant/message/aibot-message.gts +374 -0
- package/bundled-types/host-app/components/ai-assistant/message/attachments.gts +153 -0
- package/bundled-types/host-app/components/ai-assistant/message/index.gts +678 -0
- package/bundled-types/host-app/components/ai-assistant/message/meta.gts +66 -0
- package/bundled-types/host-app/components/ai-assistant/message/text-content.gts +32 -0
- package/bundled-types/host-app/components/ai-assistant/message/usage.gts +182 -0
- package/bundled-types/host-app/components/ai-assistant/message/user-message.gts +52 -0
- package/bundled-types/host-app/components/ai-assistant/new-session-button.gts +126 -0
- package/bundled-types/host-app/components/ai-assistant/new-session-settings.gts +180 -0
- package/bundled-types/host-app/components/ai-assistant/new-session.gts +83 -0
- package/bundled-types/host-app/components/ai-assistant/panel-popover.gts +102 -0
- package/bundled-types/host-app/components/ai-assistant/panel.gts +453 -0
- package/bundled-types/host-app/components/ai-assistant/past-session-item.gts +323 -0
- package/bundled-types/host-app/components/ai-assistant/past-sessions.gts +115 -0
- package/bundled-types/host-app/components/ai-assistant/rename-session.gts +144 -0
- package/bundled-types/host-app/components/ai-assistant/restore-file-modal.gts +105 -0
- package/bundled-types/host-app/components/ai-assistant/skill-menu/index.gts +190 -0
- package/bundled-types/host-app/components/ai-assistant/skill-menu/skill-toggle.gts +168 -0
- package/bundled-types/host-app/components/ai-assistant/skill-menu/usage.gts +48 -0
- package/bundled-types/host-app/components/ai-assistant/toast.gts +293 -0
- package/bundled-types/host-app/components/card-catalog/modal.gts +579 -0
- package/bundled-types/host-app/components/card-error.gts +41 -0
- package/bundled-types/host-app/components/card-instance-picker/index.gts +54 -0
- package/bundled-types/host-app/components/card-pill.gts +189 -0
- package/bundled-types/host-app/components/card-prerender.gts +880 -0
- package/bundled-types/host-app/components/card-renderer.gts +84 -0
- package/bundled-types/host-app/components/card-search/constants.ts +76 -0
- package/bundled-types/host-app/components/card-search/item-button.gts +243 -0
- package/bundled-types/host-app/components/card-search/panel.gts +150 -0
- package/bundled-types/host-app/components/card-search/search-bar.gts +218 -0
- package/bundled-types/host-app/components/card-search/search-content.gts +604 -0
- package/bundled-types/host-app/components/card-search/search-result-header.gts +165 -0
- package/bundled-types/host-app/components/card-search/search-result-section.gts +545 -0
- package/bundled-types/host-app/components/card-search/section-header.gts +117 -0
- package/bundled-types/host-app/components/editor/directory.gts +308 -0
- package/bundled-types/host-app/components/editor/file-tree.gts +69 -0
- package/bundled-types/host-app/components/editor/import-module.gts +27 -0
- package/bundled-types/host-app/components/editor/indexed-file-tree.gts +572 -0
- package/bundled-types/host-app/components/editor/recent-files.gts +141 -0
- package/bundled-types/host-app/components/file-pill.gts +206 -0
- package/bundled-types/host-app/components/head-format-preview.gts +781 -0
- package/bundled-types/host-app/components/host-mode/breadcrumb-item.gts +150 -0
- package/bundled-types/host-app/components/host-mode/breadcrumbs.gts +131 -0
- package/bundled-types/host-app/components/host-mode/card.gts +199 -0
- package/bundled-types/host-app/components/host-mode/content.gts +195 -0
- package/bundled-types/host-app/components/host-mode/stack-item.gts +310 -0
- package/bundled-types/host-app/components/host-mode/stack.gts +91 -0
- package/bundled-types/host-app/components/matrix/auth-container.gts +66 -0
- package/bundled-types/host-app/components/matrix/auth.gts +73 -0
- package/bundled-types/host-app/components/matrix/forgot-password.gts +487 -0
- package/bundled-types/host-app/components/matrix/login.gts +241 -0
- package/bundled-types/host-app/components/matrix/register-user.gts +843 -0
- package/bundled-types/host-app/components/matrix/room-message-command.gts +330 -0
- package/bundled-types/host-app/components/matrix/room-message.gts +261 -0
- package/bundled-types/host-app/components/matrix/room.gts +1872 -0
- package/bundled-types/host-app/components/matrix/user-profile.gts +99 -0
- package/bundled-types/host-app/components/modal-container.gts +171 -0
- package/bundled-types/host-app/components/operator-mode/binary-file-info.gts +77 -0
- package/bundled-types/host-app/components/operator-mode/card-adoption-chain.gts +99 -0
- package/bundled-types/host-app/components/operator-mode/card-error-detail.gts +87 -0
- package/bundled-types/host-app/components/operator-mode/card-error.gts +177 -0
- package/bundled-types/host-app/components/operator-mode/card-schema-editor.gts +616 -0
- package/bundled-types/host-app/components/operator-mode/card-url-bar.gts +197 -0
- package/bundled-types/host-app/components/operator-mode/choose-file-modal.gts +562 -0
- package/bundled-types/host-app/components/operator-mode/choose-subscription-plan-modal.gts +517 -0
- package/bundled-types/host-app/components/operator-mode/code-editor.gts +736 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/editor-indicator.gts +128 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/format-chooser.gts +592 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/inner-container.gts +162 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/left-panel-toggle.gts +267 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/module-inspector.gts +836 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/playground/field-chooser-modal.gts +97 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/playground/instance-chooser-dropdown.gts +346 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground-background.png +0 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground-panel.gts +1274 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground-preview.gts +155 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/playground/playground.gts +98 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/playground/spec-search.gts +70 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/schema-editor.gts +205 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/spec-preview-badge.gts +72 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/spec-preview.gts +432 -0
- package/bundled-types/host-app/components/operator-mode/code-submode/toggle-button.gts +72 -0
- package/bundled-types/host-app/components/operator-mode/code-submode.gts +1030 -0
- package/bundled-types/host-app/components/operator-mode/container.gts +270 -0
- package/bundled-types/host-app/components/operator-mode/context-menu-button.gts +95 -0
- package/bundled-types/host-app/components/operator-mode/copy-button.gts +277 -0
- package/bundled-types/host-app/components/operator-mode/create-file-modal.gts +1087 -0
- package/bundled-types/host-app/components/operator-mode/create-listing-modal.gts +513 -0
- package/bundled-types/host-app/components/operator-mode/definition-container/base.gts +222 -0
- package/bundled-types/host-app/components/operator-mode/definition-container/clickable.gts +59 -0
- package/bundled-types/host-app/components/operator-mode/definition-container/divider.gts +48 -0
- package/bundled-types/host-app/components/operator-mode/definition-container/index.gts +108 -0
- package/bundled-types/host-app/components/operator-mode/delete-modal.gts +123 -0
- package/bundled-types/host-app/components/operator-mode/detail-panel-selector.gts +320 -0
- package/bundled-types/host-app/components/operator-mode/detail-panel.gts +834 -0
- package/bundled-types/host-app/components/operator-mode/edit-field-modal.gts +450 -0
- package/bundled-types/host-app/components/operator-mode/error-display.gts +590 -0
- package/bundled-types/host-app/components/operator-mode/host-submode/open-site-popover.gts +127 -0
- package/bundled-types/host-app/components/operator-mode/host-submode/publishing-realm-popover.gts +159 -0
- package/bundled-types/host-app/components/operator-mode/host-submode.gts +373 -0
- package/bundled-types/host-app/components/operator-mode/interact-submode/neighbor-stack-trigger.gts +116 -0
- package/bundled-types/host-app/components/operator-mode/interact-submode.gts +1021 -0
- package/bundled-types/host-app/components/operator-mode/new-file-button.gts +187 -0
- package/bundled-types/host-app/components/operator-mode/operator-mode-overlays.gts +511 -0
- package/bundled-types/host-app/components/operator-mode/overlays.gts +342 -0
- package/bundled-types/host-app/components/operator-mode/preview-panel/fitted-format-gallery.gts +127 -0
- package/bundled-types/host-app/components/operator-mode/preview-panel/index.gts +443 -0
- package/bundled-types/host-app/components/operator-mode/preview-panel/markdown-preview.gts +175 -0
- package/bundled-types/host-app/components/operator-mode/preview-panel/metadata-panel.gts +214 -0
- package/bundled-types/host-app/components/operator-mode/preview-panel/rendered-markdown.gts +718 -0
- package/bundled-types/host-app/components/operator-mode/private-dependency-violation.gts +70 -0
- package/bundled-types/host-app/components/operator-mode/profile/profile-email.gts +686 -0
- package/bundled-types/host-app/components/operator-mode/profile/profile-settings-modal.gts +454 -0
- package/bundled-types/host-app/components/operator-mode/profile/profile-subscription.gts +170 -0
- package/bundled-types/host-app/components/operator-mode/profile-info-popover.gts +263 -0
- package/bundled-types/host-app/components/operator-mode/publish-realm-modal.gts +1529 -0
- package/bundled-types/host-app/components/operator-mode/remove-field-modal.gts +135 -0
- package/bundled-types/host-app/components/operator-mode/send-error-to-ai-assistant.gts +195 -0
- package/bundled-types/host-app/components/operator-mode/stack-item.gts +1341 -0
- package/bundled-types/host-app/components/operator-mode/stack.gts +191 -0
- package/bundled-types/host-app/components/operator-mode/submode-layout.gts +781 -0
- package/bundled-types/host-app/components/operator-mode/syntax-error-display.gts +72 -0
- package/bundled-types/host-app/components/operator-mode/workspace-chooser/add-workspace.gts +282 -0
- package/bundled-types/host-app/components/operator-mode/workspace-chooser/index.gts +307 -0
- package/bundled-types/host-app/components/operator-mode/workspace-chooser/item-container.gts +50 -0
- package/bundled-types/host-app/components/operator-mode/workspace-chooser/workspace-loading-indicator.gts +50 -0
- package/bundled-types/host-app/components/operator-mode/workspace-chooser/workspace.gts +1092 -0
- package/bundled-types/host-app/components/pill-menu/index.gts +281 -0
- package/bundled-types/host-app/components/pill-menu/usage.gts +64 -0
- package/bundled-types/host-app/components/prerendered-card-search.gts +274 -0
- package/bundled-types/host-app/components/realm-dropdown.gts +209 -0
- package/bundled-types/host-app/components/realm-picker/index.gts +142 -0
- package/bundled-types/host-app/components/search-sheet/index.gts +426 -0
- package/bundled-types/host-app/components/search-sheet/usage.gts +99 -0
- package/bundled-types/host-app/components/submode-switcher.gts +260 -0
- package/bundled-types/host-app/components/type-picker/index.gts +111 -0
- package/bundled-types/host-app/components/with-known-realms-loaded.gts +47 -0
- package/bundled-types/host-app/components/with-loaded-realm.gts +39 -0
- package/bundled-types/host-app/components/with-subscription-data.gts +247 -0
- package/bundled-types/host-app/config/environment.ts +66 -0
- package/bundled-types/host-app/deprecation-workflow.js +30 -0
- package/bundled-types/host-app/lib/browser-queue.ts +198 -0
- package/bundled-types/host-app/lib/codemirror-context.ts +1081 -0
- package/bundled-types/host-app/lib/command-definitions.ts +41 -0
- package/bundled-types/host-app/lib/download-realm.ts +9 -0
- package/bundled-types/host-app/lib/example-card-helpers.ts +99 -0
- package/bundled-types/host-app/lib/externals.ts +247 -0
- package/bundled-types/host-app/lib/field-path-parser.ts +520 -0
- package/bundled-types/host-app/lib/file-def-manager.ts +712 -0
- package/bundled-types/host-app/lib/file-upload-state.ts +6 -0
- package/bundled-types/host-app/lib/formatted-message/utils.ts +272 -0
- package/bundled-types/host-app/lib/gc-card-store.ts +1084 -0
- package/bundled-types/host-app/lib/host-base-command.ts +29 -0
- package/bundled-types/host-app/lib/html-component.ts +144 -0
- package/bundled-types/host-app/lib/html-to-markdown.ts +96 -0
- package/bundled-types/host-app/lib/isolated-render.gts +90 -0
- package/bundled-types/host-app/lib/known-file-meta-urls.ts +17 -0
- package/bundled-types/host-app/lib/limited-set.ts +68 -0
- package/bundled-types/host-app/lib/matrix-classes/member.ts +28 -0
- package/bundled-types/host-app/lib/matrix-classes/message-builder.ts +444 -0
- package/bundled-types/host-app/lib/matrix-classes/message-code-patch-result.ts +44 -0
- package/bundled-types/host-app/lib/matrix-classes/message-command.ts +109 -0
- package/bundled-types/host-app/lib/matrix-classes/message.ts +239 -0
- package/bundled-types/host-app/lib/matrix-classes/room.ts +174 -0
- package/bundled-types/host-app/lib/matrix-utils.ts +114 -0
- package/bundled-types/host-app/lib/mutex.ts +62 -0
- package/bundled-types/host-app/lib/prerender-fetch-headers.ts +46 -0
- package/bundled-types/host-app/lib/prerender-util.ts +31 -0
- package/bundled-types/host-app/lib/public-path.ts +1 -0
- package/bundled-types/host-app/lib/random-name.ts +26 -0
- package/bundled-types/host-app/lib/realm-utils.ts +45 -0
- package/bundled-types/host-app/lib/search-cache-key.ts +33 -0
- package/bundled-types/host-app/lib/search-in-flight-key.ts +28 -0
- package/bundled-types/host-app/lib/search-replace-block-parsing.ts +101 -0
- package/bundled-types/host-app/lib/setup-globals.ts +15 -0
- package/bundled-types/host-app/lib/sqlite-adapter.ts +510 -0
- package/bundled-types/host-app/lib/stack-item.ts +164 -0
- package/bundled-types/host-app/lib/utils.ts +84 -0
- package/bundled-types/host-app/lib/window-error-handler.ts +132 -0
- package/bundled-types/host-app/router.ts +31 -0
- package/bundled-types/host-app/services/ai-assistant-panel-service.ts +850 -0
- package/bundled-types/host-app/services/billing-service.ts +208 -0
- package/bundled-types/host-app/services/card-service.ts +373 -0
- package/bundled-types/host-app/services/card-type-service.ts +226 -0
- package/bundled-types/host-app/services/code-semantics-service.ts +297 -0
- package/bundled-types/host-app/services/command-service.ts +975 -0
- package/bundled-types/host-app/services/environment-service.ts +26 -0
- package/bundled-types/host-app/services/error-display.ts +42 -0
- package/bundled-types/host-app/services/file-upload.ts +212 -0
- package/bundled-types/host-app/services/host-mode-service.ts +400 -0
- package/bundled-types/host-app/services/host-mode-state-service.ts +160 -0
- package/bundled-types/host-app/services/loader-service.ts +148 -0
- package/bundled-types/host-app/services/local-indexer.ts +68 -0
- package/bundled-types/host-app/services/local-persistence-service.ts +296 -0
- package/bundled-types/host-app/services/logger-service.ts +13 -0
- package/bundled-types/host-app/services/matrix-sdk-loader.ts +346 -0
- package/bundled-types/host-app/services/matrix-service.ts +2288 -0
- package/bundled-types/host-app/services/message-service.ts +84 -0
- package/bundled-types/host-app/services/module-contents-service.ts +333 -0
- package/bundled-types/host-app/services/monaco-service.ts +333 -0
- package/bundled-types/host-app/services/network.ts +101 -0
- package/bundled-types/host-app/services/operator-mode-state-service.ts +1593 -0
- package/bundled-types/host-app/services/playground-panel-service.ts +236 -0
- package/bundled-types/host-app/services/queue.ts +30 -0
- package/bundled-types/host-app/services/realm-info-service.ts +37 -0
- package/bundled-types/host-app/services/realm-server.ts +1211 -0
- package/bundled-types/host-app/services/realm.ts +1413 -0
- package/bundled-types/host-app/services/recent-cards-service.ts +174 -0
- package/bundled-types/host-app/services/recent-files-service.ts +224 -0
- package/bundled-types/host-app/services/render-error-state.ts +55 -0
- package/bundled-types/host-app/services/render-service.ts +362 -0
- package/bundled-types/host-app/services/render-store.ts +27 -0
- package/bundled-types/host-app/services/reset.ts +19 -0
- package/bundled-types/host-app/services/scroll-position-service.ts +81 -0
- package/bundled-types/host-app/services/spec-panel-service.ts +107 -0
- package/bundled-types/host-app/services/store.ts +2540 -0
- package/bundled-types/host-app/utils/assert-never.ts +3 -0
- package/bundled-types/host-app/utils/auth-error-guard.ts +183 -0
- package/bundled-types/host-app/utils/auth-service-worker-registration.ts +123 -0
- package/bundled-types/host-app/utils/card-search/query-builder.ts +169 -0
- package/bundled-types/host-app/utils/card-search/section-pagination.ts +57 -0
- package/bundled-types/host-app/utils/card-search/sections.ts +240 -0
- package/bundled-types/host-app/utils/card-search/type-filter.ts +124 -0
- package/bundled-types/host-app/utils/card-search/types.ts +11 -0
- package/bundled-types/host-app/utils/card-search/url.ts +27 -0
- package/bundled-types/host-app/utils/clipboard.ts +23 -0
- package/bundled-types/host-app/utils/editor/boxel-formatter.ts +65 -0
- package/bundled-types/host-app/utils/editor/editor-language.ts +88 -0
- package/bundled-types/host-app/utils/editor/monaco-test-waiter.ts +302 -0
- package/bundled-types/host-app/utils/file-def-attributes-extractor.ts +438 -0
- package/bundled-types/host-app/utils/file-name.ts +38 -0
- package/bundled-types/host-app/utils/id-from-card-or-url.ts +11 -0
- package/bundled-types/host-app/utils/lint-formatting.ts +57 -0
- package/bundled-types/host-app/utils/local-storage-keys.ts +28 -0
- package/bundled-types/host-app/utils/normalized-dir-path.ts +3 -0
- package/bundled-types/host-app/utils/prettify-messages.ts +21 -0
- package/bundled-types/host-app/utils/prettify-prompts.ts +21 -0
- package/bundled-types/host-app/utils/realm-index-boilerplate.ts +27 -0
- package/bundled-types/host-app/utils/register-boxel-transition.ts +17 -0
- package/bundled-types/host-app/utils/render-desync-detector.ts +362 -0
- package/bundled-types/host-app/utils/render-error.ts +455 -0
- package/bundled-types/host-app/utils/render-timer-stub.ts +249 -0
- package/bundled-types/host-app/utils/run-while-active.ts +14 -0
- package/bundled-types/host-app/utils/schema-editor.ts +25 -0
- package/bundled-types/host-app/utils/text-suggestion.ts +82 -0
- package/bundled-types/host-app/utils/titleize.ts +10 -0
- package/bundled-types/host-app/utils/uuid.ts +13 -0
- package/bundled-types/host-tests/helpers/adapter.ts +464 -0
- package/bundled-types/host-tests/helpers/base-realm.ts +464 -0
- package/bundled-types/host-tests/helpers/cards/view-card-demo.ts +119 -0
- package/bundled-types/host-tests/helpers/field-test-helpers.gts +54 -0
- package/bundled-types/host-tests/helpers/image-fixture.ts +3 -0
- package/bundled-types/host-tests/helpers/index.gts +2099 -0
- package/bundled-types/host-tests/helpers/indexer.ts +293 -0
- package/bundled-types/host-tests/helpers/interact-submode-setup.gts +551 -0
- package/bundled-types/host-tests/helpers/mock-matrix/_client.ts +1042 -0
- package/bundled-types/host-tests/helpers/mock-matrix/_sdk.ts +71 -0
- package/bundled-types/host-tests/helpers/mock-matrix/_server-state.ts +343 -0
- package/bundled-types/host-tests/helpers/mock-matrix/_sliding-sync.ts +140 -0
- package/bundled-types/host-tests/helpers/mock-matrix/_utils.ts +146 -0
- package/bundled-types/host-tests/helpers/mock-matrix.ts +200 -0
- package/bundled-types/host-tests/helpers/operator-mode-parameters-match.ts +71 -0
- package/bundled-types/host-tests/helpers/operator-mode-state.ts +18 -0
- package/bundled-types/host-tests/helpers/percy-snapshot.ts +228 -0
- package/bundled-types/host-tests/helpers/playground.ts +130 -0
- package/bundled-types/host-tests/helpers/realm-server-mock/index.ts +100 -0
- package/bundled-types/host-tests/helpers/realm-server-mock/routes.ts +617 -0
- package/bundled-types/host-tests/helpers/realm-server-mock/types.ts +24 -0
- package/bundled-types/host-tests/helpers/recent-files-cards.ts +86 -0
- package/bundled-types/host-tests/helpers/render-component.ts +40 -0
- package/bundled-types/host-tests/helpers/setup-qunit.js +164 -0
- package/bundled-types/host-tests/helpers/setup.ts +349 -0
- package/bundled-types/host-tests/helpers/shard-warmup.ts +72 -0
- package/bundled-types/host-tests/helpers/stream.ts +60 -0
- package/bundled-types/host-tests/helpers/test-auth.ts +27 -0
- package/bundled-types/host-tests/helpers/test-realm-registry.ts +23 -0
- package/bundled-types/host-tests/helpers/test-realm-service-worker.ts +92 -0
- package/bundled-types/host-tests/helpers/uncaught-exceptions.ts +16 -0
- package/bundled-types/host-tests/helpers/visit-operator-mode.ts +39 -0
- package/bundled-types/host-types/@cardstack/host/index.d.ts +3 -0
- package/bundled-types/host-types/@joplin/turndown-plugin-gfm/index.d.ts +15 -0
- package/bundled-types/host-types/@sqlite.org/sqlite-wasm/index.d.ts +122 -0
- package/bundled-types/host-types/ember-click-outside/modifiers/on-click-outside.ts +16 -0
- package/bundled-types/host-types/ember-concurrency/helpers/perform.d.ts +3 -0
- package/bundled-types/host-types/ember-css-url/index.d.ts +15 -0
- package/bundled-types/host-types/ember-data/types/registries/model.d.ts +6 -0
- package/bundled-types/host-types/ember-elsewhere/from-elsewhere.d.ts +12 -0
- package/bundled-types/host-types/ember-elsewhere/to-elsewhere.d.ts +16 -0
- package/bundled-types/host-types/ember-focus-trap/index.d.ts +4 -0
- package/bundled-types/host-types/ember-keyboard/modifiers/on-key.d.ts +15 -0
- package/bundled-types/host-types/index.d.ts +6 -0
- package/bundled-types/local-types/eslint-js.d.ts +5 -0
- package/bundled-types/local-types/index.d.ts +115 -0
- package/bundled-types/local-types/marked-gfm-heading-id.d.ts +12 -0
- package/bundled-types/local-types/matrix-js-sdk/index.d.ts +11 -0
- package/bundled-types/local-types/package.json +13 -0
- package/bundled-types/shims/boxel-cli-shims.d.ts +10 -0
- package/dist/index.js +100 -100
- package/package.json +13 -7
- package/src/commands/parse.ts +277 -34
- package/src/commands/realm/publish.ts +10 -1
- package/src/commands/realm/unpublish.ts +2 -3
- package/src/lib/describe-fetch-error.ts +25 -0
|
@@ -0,0 +1,1593 @@
|
|
|
1
|
+
import { getOwner } from '@ember/application';
|
|
2
|
+
import type Owner from '@ember/owner';
|
|
3
|
+
import type RouterService from '@ember/routing/router-service';
|
|
4
|
+
import { scheduleOnce } from '@ember/runloop';
|
|
5
|
+
import Service, { service } from '@ember/service';
|
|
6
|
+
|
|
7
|
+
import { tracked, cached } from '@glimmer/tracking';
|
|
8
|
+
|
|
9
|
+
import { task, restartableTask } from 'ember-concurrency';
|
|
10
|
+
import window from 'ember-window-mock';
|
|
11
|
+
import stringify from 'safe-stable-stringify';
|
|
12
|
+
import { TrackedArray, TrackedMap, TrackedObject } from 'tracked-built-ins';
|
|
13
|
+
|
|
14
|
+
import type {
|
|
15
|
+
CodeRef,
|
|
16
|
+
RealmResourceIdentifier,
|
|
17
|
+
} from '@cardstack/runtime-common';
|
|
18
|
+
import {
|
|
19
|
+
cardIdToURL,
|
|
20
|
+
rri,
|
|
21
|
+
RealmPaths,
|
|
22
|
+
type LocalPath,
|
|
23
|
+
isResolvedCodeRef,
|
|
24
|
+
isCardInstance,
|
|
25
|
+
isRealmIndexCardId,
|
|
26
|
+
isLocalId,
|
|
27
|
+
localId as localIdSymbol,
|
|
28
|
+
Deferred,
|
|
29
|
+
SupportedMimeType,
|
|
30
|
+
internalKeyFor,
|
|
31
|
+
realmURL as realmURLSymbol,
|
|
32
|
+
} from '@cardstack/runtime-common';
|
|
33
|
+
|
|
34
|
+
import type { Submode } from '@cardstack/host/components/submode-switcher';
|
|
35
|
+
import { Submodes } from '@cardstack/host/components/submode-switcher';
|
|
36
|
+
import { StackItem, type StackItemType } from '@cardstack/host/lib/stack-item';
|
|
37
|
+
|
|
38
|
+
import {
|
|
39
|
+
file,
|
|
40
|
+
isReady,
|
|
41
|
+
type FileResource,
|
|
42
|
+
} from '@cardstack/host/resources/file';
|
|
43
|
+
import { maybe } from '@cardstack/host/resources/maybe';
|
|
44
|
+
import type LoaderService from '@cardstack/host/services/loader-service';
|
|
45
|
+
import type MessageService from '@cardstack/host/services/message-service';
|
|
46
|
+
import type MonacoService from '@cardstack/host/services/monaco-service';
|
|
47
|
+
import type PlaygroundPanelService from '@cardstack/host/services/playground-panel-service';
|
|
48
|
+
import type { PlaygroundSelection } from '@cardstack/host/services/playground-panel-service';
|
|
49
|
+
import type Realm from '@cardstack/host/services/realm';
|
|
50
|
+
import type RealmServer from '@cardstack/host/services/realm-server';
|
|
51
|
+
import type RecentCardsService from '@cardstack/host/services/recent-cards-service';
|
|
52
|
+
import type RecentFilesService from '@cardstack/host/services/recent-files-service';
|
|
53
|
+
|
|
54
|
+
import type { CardDef, Format } from 'https://cardstack.com/base/card-api';
|
|
55
|
+
|
|
56
|
+
import type { BoxelContext } from 'https://cardstack.com/base/matrix-event';
|
|
57
|
+
|
|
58
|
+
import { removeFileExtension } from '../utils/card-search/types';
|
|
59
|
+
|
|
60
|
+
import {
|
|
61
|
+
AiAssistantOpen,
|
|
62
|
+
ModuleInspectorSelections,
|
|
63
|
+
} from '../utils/local-storage-keys';
|
|
64
|
+
|
|
65
|
+
import { normalizeDirPath } from '../utils/normalized-dir-path';
|
|
66
|
+
|
|
67
|
+
import type CardService from './card-service';
|
|
68
|
+
import type CodeSemanticsService from './code-semantics-service';
|
|
69
|
+
import type ErrorDisplayService from './error-display';
|
|
70
|
+
import type MatrixService from './matrix-service';
|
|
71
|
+
import type NetworkService from './network';
|
|
72
|
+
import type { RecentFile } from './recent-files-service';
|
|
73
|
+
import type ResetService from './reset';
|
|
74
|
+
import type SpecPanelService from './spec-panel-service';
|
|
75
|
+
import type StoreService from './store';
|
|
76
|
+
import type { Stack } from '../components/operator-mode/interact-submode';
|
|
77
|
+
|
|
78
|
+
import type IndexController from '../controllers';
|
|
79
|
+
|
|
80
|
+
export interface CreateListingModalPayload {
|
|
81
|
+
codeRef: CodeRef;
|
|
82
|
+
targetRealm: string;
|
|
83
|
+
openCardIds?: RealmResourceIdentifier[];
|
|
84
|
+
declarationKind: 'card' | 'field';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Below types form a raw POJO representation of operator mode state.
|
|
88
|
+
// This state differs from OperatorModeState in that it only contains cards that have been saved (i.e. have an ID).
|
|
89
|
+
// This is because we don't have a way to serialize a stack configuration of linked cards that have not been saved yet.
|
|
90
|
+
|
|
91
|
+
export interface OperatorModeState {
|
|
92
|
+
stacks: Stack[];
|
|
93
|
+
submode: Submode;
|
|
94
|
+
codePath: URL | null;
|
|
95
|
+
hostModePrimaryCard: string | null;
|
|
96
|
+
hostModeStack: string[];
|
|
97
|
+
aiAssistantOpen: boolean;
|
|
98
|
+
fileView?: FileView;
|
|
99
|
+
openDirs: Map<string, string[]>;
|
|
100
|
+
codeSelection?: string;
|
|
101
|
+
fieldSelection?: string;
|
|
102
|
+
moduleInspector?: ModuleInspectorView;
|
|
103
|
+
newFileDropdownOpen?: boolean;
|
|
104
|
+
cardPreviewFormat: Format;
|
|
105
|
+
workspaceChooserOpened?: boolean;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
interface CardItem {
|
|
109
|
+
id: string;
|
|
110
|
+
format: 'isolated' | 'edit' | 'head';
|
|
111
|
+
type?: StackItemType;
|
|
112
|
+
useBaseTemplate?: boolean;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface SerializedExpandedStackItem {
|
|
116
|
+
id: string;
|
|
117
|
+
stackIndex: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type FileView = 'inspector' | 'browser';
|
|
121
|
+
|
|
122
|
+
type SerializedItem = CardItem;
|
|
123
|
+
type SerializedStack = SerializedItem[];
|
|
124
|
+
|
|
125
|
+
export type SerializedState = {
|
|
126
|
+
stacks: SerializedStack[];
|
|
127
|
+
submode?: Submode;
|
|
128
|
+
codePath?: string;
|
|
129
|
+
trail?: string[];
|
|
130
|
+
fileView?: FileView;
|
|
131
|
+
openDirs?: Record<string, string[]>;
|
|
132
|
+
codeSelection?: string;
|
|
133
|
+
fieldSelection?: string;
|
|
134
|
+
aiAssistantOpen?: boolean;
|
|
135
|
+
moduleInspector?: ModuleInspectorView;
|
|
136
|
+
cardPreviewFormat?: Format;
|
|
137
|
+
workspaceChooserOpened?: boolean;
|
|
138
|
+
expandedStackItem?: SerializedExpandedStackItem;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
interface OpenFileSubscriber {
|
|
142
|
+
onStateChange: (state: FileResource['state']) => void;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export type ModuleInspectorView = 'schema' | 'spec' | 'preview';
|
|
146
|
+
export const DEFAULT_MODULE_INSPECTOR_VIEW: ModuleInspectorView = 'schema';
|
|
147
|
+
|
|
148
|
+
// Read the user's persisted AI Assistant open/closed preference. Defaults to
|
|
149
|
+
// `true` for first-ever visits; URL state still takes precedence over this.
|
|
150
|
+
function readPersistedAiAssistantOpen(): boolean {
|
|
151
|
+
let raw = window.localStorage.getItem(AiAssistantOpen);
|
|
152
|
+
if (raw === 'true') return true;
|
|
153
|
+
if (raw === 'false') return false;
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export default class OperatorModeStateService extends Service {
|
|
158
|
+
@tracked private _state: OperatorModeState = new TrackedObject({
|
|
159
|
+
stacks: new TrackedArray<Stack>([]),
|
|
160
|
+
submode: Submodes.Interact,
|
|
161
|
+
codePath: null,
|
|
162
|
+
hostModePrimaryCard: null,
|
|
163
|
+
hostModeStack: [],
|
|
164
|
+
openDirs: new TrackedMap<string, string[]>(),
|
|
165
|
+
aiAssistantOpen: readPersistedAiAssistantOpen(),
|
|
166
|
+
newFileDropdownOpen: false,
|
|
167
|
+
cardPreviewFormat: 'isolated' as Format,
|
|
168
|
+
workspaceChooserOpened: false,
|
|
169
|
+
});
|
|
170
|
+
private cachedRealmURL: URL | null = null;
|
|
171
|
+
private openFileSubscribers: OpenFileSubscriber[] = [];
|
|
172
|
+
private cardTitles = new TrackedMap<string, string>();
|
|
173
|
+
|
|
174
|
+
private moduleInspectorHistory: Record<string, ModuleInspectorView>;
|
|
175
|
+
|
|
176
|
+
@tracked profileSettingsOpen = false;
|
|
177
|
+
@tracked createListingModalPayload?: CreateListingModalPayload;
|
|
178
|
+
|
|
179
|
+
// Per-card expanded-mode intent. Keyed by stack-item instance id so the
|
|
180
|
+
// user's expand intent survives bury/pop cycles within a stack:
|
|
181
|
+
// when a card is pushed deeper, stack-item reads isTopCard=false
|
|
182
|
+
// and renders normally; when it pops back to the top, the stored
|
|
183
|
+
// intent re-applies and the card re-expands.
|
|
184
|
+
private expandedStackItems: TrackedMap<string, boolean> = new TrackedMap();
|
|
185
|
+
isStackItemExpanded(itemKey: string): boolean {
|
|
186
|
+
return this.expandedStackItems.get(itemKey) ?? false;
|
|
187
|
+
}
|
|
188
|
+
setStackItemExpanded(itemKey: string, value: boolean) {
|
|
189
|
+
if (value) {
|
|
190
|
+
// Only one card can be expanded at a time — clear all others so
|
|
191
|
+
// the same card open in two stacks can't leave both expanded.
|
|
192
|
+
this.expandedStackItems.clear();
|
|
193
|
+
this.expandedStackItems.set(itemKey, true);
|
|
194
|
+
} else {
|
|
195
|
+
this.expandedStackItems.delete(itemKey);
|
|
196
|
+
}
|
|
197
|
+
this.schedulePersist();
|
|
198
|
+
}
|
|
199
|
+
// True when at least one stack's TOP card has expand intent — used
|
|
200
|
+
// to drive the bar's glass-morphism + .has-expanded-card class. Only
|
|
201
|
+
// top cards count: when a card with expand intent gets buried under
|
|
202
|
+
// a new stack item, the intent is retained (so it auto-re-expands
|
|
203
|
+
// on return) but the bar should drop its frost so the new top card
|
|
204
|
+
// stacks normally without a frosted scrim. Same per-level: A
|
|
205
|
+
// expanded → push B → A buried + intent kept, frost off → B top
|
|
206
|
+
// (no intent yet) → expand B → frost on → push C → B buried +
|
|
207
|
+
// intent kept, frost off; close C → B top again, intent fires,
|
|
208
|
+
// frost back on; close B → A top again, intent fires, frost on.
|
|
209
|
+
get hasAnyStackItemExpanded(): boolean {
|
|
210
|
+
if (this.expandedStackItems.size === 0) return false;
|
|
211
|
+
return this._state.stacks.some((stack) => {
|
|
212
|
+
const top = stack[stack.length - 1];
|
|
213
|
+
return top && this.expandedStackItems.has(top.instanceId);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Slot in submode-layout's top bar where an EXPANDED stack item's
|
|
218
|
+
// CardHeader portals itself. Captured by submode-layout via
|
|
219
|
+
// captureElement modifier on insert. Stack-item reads this and uses
|
|
220
|
+
// {{#in-element}} to project its header pill into the bar when
|
|
221
|
+
// isExpanded — replacing the inline card header for the expanded
|
|
222
|
+
// mode only. When collapsed, the inline header reappears.
|
|
223
|
+
@tracked expandedCardHeaderElement: HTMLElement | null = null;
|
|
224
|
+
|
|
225
|
+
@service declare private cardService: CardService;
|
|
226
|
+
@service declare private codeSemanticsService: CodeSemanticsService;
|
|
227
|
+
@service declare private errorDisplay: ErrorDisplayService;
|
|
228
|
+
@service declare private loaderService: LoaderService;
|
|
229
|
+
@service declare private messageService: MessageService;
|
|
230
|
+
@service declare private monacoService: MonacoService;
|
|
231
|
+
@service declare private realm: Realm;
|
|
232
|
+
@service declare private realmServer: RealmServer;
|
|
233
|
+
@service declare private recentCardsService: RecentCardsService;
|
|
234
|
+
@service declare private recentFilesService: RecentFilesService;
|
|
235
|
+
@service declare private router: RouterService;
|
|
236
|
+
@service declare private reset: ResetService;
|
|
237
|
+
@service declare private network: NetworkService;
|
|
238
|
+
@service declare private matrixService: MatrixService;
|
|
239
|
+
@service declare private store: StoreService;
|
|
240
|
+
@service declare private playgroundPanelService: PlaygroundPanelService;
|
|
241
|
+
@service declare private specPanelService: SpecPanelService;
|
|
242
|
+
|
|
243
|
+
constructor(owner: Owner) {
|
|
244
|
+
super(owner);
|
|
245
|
+
this.reset.register(this);
|
|
246
|
+
|
|
247
|
+
let moduleInspectorHistory = window.localStorage.getItem(
|
|
248
|
+
ModuleInspectorSelections,
|
|
249
|
+
);
|
|
250
|
+
this.moduleInspectorHistory = new TrackedObject(
|
|
251
|
+
moduleInspectorHistory ? JSON.parse(moduleInspectorHistory) : {},
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
toggleProfileSettings = () => {
|
|
256
|
+
this.profileSettingsOpen = !this.profileSettingsOpen;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
get state() {
|
|
260
|
+
return {
|
|
261
|
+
stacks: this._state.stacks,
|
|
262
|
+
submode: this._state.submode,
|
|
263
|
+
codePath: this._state.codePath,
|
|
264
|
+
hostModeStack: this._state.hostModeStack,
|
|
265
|
+
hostModePrimaryCard: this._state.hostModePrimaryCard,
|
|
266
|
+
fileView: this._state.fileView,
|
|
267
|
+
openDirs: this._state.openDirs,
|
|
268
|
+
codeSelection: this._state.codeSelection,
|
|
269
|
+
fieldSelection: this._state.fieldSelection,
|
|
270
|
+
aiAssistantOpen: this._state.aiAssistantOpen,
|
|
271
|
+
moduleInspector: this._state.moduleInspector,
|
|
272
|
+
newFileDropdownOpen: this._state.newFileDropdownOpen,
|
|
273
|
+
cardPreviewFormat: this._state.cardPreviewFormat,
|
|
274
|
+
workspaceChooserOpened: this._state.workspaceChooserOpened,
|
|
275
|
+
} as const;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
get aiAssistantOpen() {
|
|
279
|
+
return this._state.aiAssistantOpen;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
openAiAssistant = () => {
|
|
283
|
+
this._state.aiAssistantOpen = true;
|
|
284
|
+
window.localStorage.setItem(AiAssistantOpen, 'true');
|
|
285
|
+
this.schedulePersist();
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
closeAiAssistant = () => {
|
|
289
|
+
this._state.aiAssistantOpen = false;
|
|
290
|
+
window.localStorage.setItem(AiAssistantOpen, 'false');
|
|
291
|
+
this.schedulePersist();
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
showCreateListingModal = (payload: CreateListingModalPayload) => {
|
|
295
|
+
this.createListingModalPayload = payload;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
dismissCreateListingModal = () => {
|
|
299
|
+
this.createListingModalPayload = undefined;
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
setNewFileDropdownOpen = () => {
|
|
303
|
+
this._state.newFileDropdownOpen = true;
|
|
304
|
+
this.schedulePersist();
|
|
305
|
+
};
|
|
306
|
+
setNewFileDropdownClosed = () => {
|
|
307
|
+
this._state.newFileDropdownOpen = false;
|
|
308
|
+
this.schedulePersist();
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
resetState() {
|
|
312
|
+
this.getOpenCards.cancelAll();
|
|
313
|
+
this.setCardTitleTask.cancelAll();
|
|
314
|
+
this._state = new TrackedObject({
|
|
315
|
+
stacks: new TrackedArray([]),
|
|
316
|
+
submode: Submodes.Interact,
|
|
317
|
+
codePath: null,
|
|
318
|
+
hostModePrimaryCard: null,
|
|
319
|
+
hostModeStack: new TrackedArray([]),
|
|
320
|
+
openDirs: new TrackedMap<string, string[]>(),
|
|
321
|
+
aiAssistantOpen: readPersistedAiAssistantOpen(),
|
|
322
|
+
moduleInspector: DEFAULT_MODULE_INSPECTOR_VIEW,
|
|
323
|
+
newFileDropdownOpen: false,
|
|
324
|
+
cardPreviewFormat: 'isolated' as Format,
|
|
325
|
+
workspaceChooserOpened: true,
|
|
326
|
+
});
|
|
327
|
+
this.cachedRealmURL = null;
|
|
328
|
+
this.openFileSubscribers = [];
|
|
329
|
+
this.cardTitles = new TrackedMap();
|
|
330
|
+
this.moduleInspectorHistory = {};
|
|
331
|
+
this.profileSettingsOpen = false;
|
|
332
|
+
this.createListingModalPayload = undefined;
|
|
333
|
+
this.expandedStackItems.clear();
|
|
334
|
+
window.localStorage.removeItem(ModuleInspectorSelections);
|
|
335
|
+
this.schedulePersist();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
restore(rawState: SerializedState) {
|
|
339
|
+
this._state = this.deserialize(rawState);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
addItemToStack(item: StackItem) {
|
|
343
|
+
let stackIndex = item.stackIndex;
|
|
344
|
+
if (!this._state.stacks[stackIndex]) {
|
|
345
|
+
this._state.stacks[stackIndex] = new TrackedArray([]);
|
|
346
|
+
}
|
|
347
|
+
if (
|
|
348
|
+
item.id &&
|
|
349
|
+
this._state.stacks[stackIndex].find((i: StackItem) => i.id === item.id)
|
|
350
|
+
) {
|
|
351
|
+
// this card is already in the stack, do nothing (maybe we could hoist
|
|
352
|
+
// this card to the top instead?)
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
// Note: expand intent is retained on the buried card so that
|
|
356
|
+
// when the topping card closes and the previously-expanded card
|
|
357
|
+
// returns to top, it auto-re-expands. The visual collapse is
|
|
358
|
+
// already handled by isExpanded = isTopCard && isExpandedIntent
|
|
359
|
+
// — a buried card never renders as expanded.
|
|
360
|
+
this._state.stacks[stackIndex].push(item);
|
|
361
|
+
if (item.id) {
|
|
362
|
+
this.recentCardsService.add(item.id);
|
|
363
|
+
}
|
|
364
|
+
this.schedulePersist();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
replaceCardOnStack(
|
|
368
|
+
oldId: string,
|
|
369
|
+
newId: string,
|
|
370
|
+
stackIndex: number,
|
|
371
|
+
format: Format = 'edit',
|
|
372
|
+
): StackItem {
|
|
373
|
+
let stack = this._state.stacks[stackIndex];
|
|
374
|
+
if (!stack) {
|
|
375
|
+
throw new Error(`Stack ${stackIndex} does not exist`);
|
|
376
|
+
}
|
|
377
|
+
let normalizedOldId = oldId.replace(/\.json$/, '');
|
|
378
|
+
let item = this.findCardInStack(normalizedOldId, stackIndex);
|
|
379
|
+
let newItem = item.clone({
|
|
380
|
+
id: newId,
|
|
381
|
+
format,
|
|
382
|
+
});
|
|
383
|
+
this.replaceItemInStack(item, newItem);
|
|
384
|
+
return newItem;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async deleteCard(cardId: string) {
|
|
388
|
+
let cardRealmUrl = (await this.network.authedFetch(cardId)).headers.get(
|
|
389
|
+
'X-Boxel-Realm-Url',
|
|
390
|
+
);
|
|
391
|
+
if (!cardRealmUrl) {
|
|
392
|
+
throw new Error(`Could not determine the realm for card "${cardId}"`);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
await this.store.delete(cardId);
|
|
396
|
+
|
|
397
|
+
// remove all stack items for the deleted card
|
|
398
|
+
let items: StackItem[] = [];
|
|
399
|
+
for (let stack of this._state.stacks || []) {
|
|
400
|
+
items.push(
|
|
401
|
+
...(stack.filter(
|
|
402
|
+
(i: StackItem) => i.id && removeFileExtension(i.id) === cardId,
|
|
403
|
+
) as StackItem[]),
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
for (let item of items) {
|
|
407
|
+
this.trimItemsFromStack(item);
|
|
408
|
+
}
|
|
409
|
+
let realmPaths = new RealmPaths(new URL(cardRealmUrl));
|
|
410
|
+
let cardPath = realmPaths.local(rri(`${cardId}.json`));
|
|
411
|
+
this.recentFilesService.removeRecentFile(cardPath);
|
|
412
|
+
this.recentCardsService.remove(cardId);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async copySource(fromUrl: string, toUrl: string) {
|
|
416
|
+
await this.cardService.copySource(new URL(fromUrl), new URL(toUrl));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
trimItemsFromStack(item: StackItem) {
|
|
420
|
+
let stackIndex = item.stackIndex;
|
|
421
|
+
let stack = this._state.stacks[stackIndex];
|
|
422
|
+
if (!stack) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
let itemIndex = stack.indexOf(item);
|
|
426
|
+
if (itemIndex === -1) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
stack.splice(itemIndex); // Remove anything above the item
|
|
430
|
+
|
|
431
|
+
// If the resulting stack is now empty, remove it
|
|
432
|
+
if (this.stackIsEmpty(stackIndex) && this._state.stacks.length >= 1) {
|
|
433
|
+
this._state.stacks.splice(stackIndex, 1);
|
|
434
|
+
|
|
435
|
+
// If we just removed the last item in the stack, and we also removed the stack because of that, we need
|
|
436
|
+
// to update the stackIndex of all items in the stacks that come after the removed stack.
|
|
437
|
+
// This is another code smell that the stackIndex should perhaps not not live in the item. For now, we keep it for convenience.
|
|
438
|
+
this._state.stacks
|
|
439
|
+
.filter((_, stackIndex) => stackIndex >= item.stackIndex)
|
|
440
|
+
.forEach((stack, realStackIndex) => {
|
|
441
|
+
stack.forEach((stackItem: StackItem) => {
|
|
442
|
+
if (stackItem.stackIndex !== realStackIndex) {
|
|
443
|
+
stackItem.stackIndex = realStackIndex;
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (this._state.stacks.length === 0) {
|
|
450
|
+
const realmURL = this.getRealmURLFromItemId(item.id);
|
|
451
|
+
const isIndexCard = isRealmIndexCardId(item.id, realmURL);
|
|
452
|
+
if (isIndexCard) {
|
|
453
|
+
// Only open workspace chooser if the trimmed item was an index card
|
|
454
|
+
this._state.workspaceChooserOpened = true;
|
|
455
|
+
} else {
|
|
456
|
+
// If the trimmed item was not an index card, add an index card to the stack
|
|
457
|
+
const indexCardId = `${realmURL}index`;
|
|
458
|
+
const indexCardItem = this.createStackItem(indexCardId, 0);
|
|
459
|
+
this.addItemToStack(indexCardItem);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
this.schedulePersist();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
popItemFromStack(stackIndex: number) {
|
|
467
|
+
let stack = this._state.stacks[stackIndex];
|
|
468
|
+
if (!stack) {
|
|
469
|
+
throw new Error(`No stack at index ${stackIndex}`);
|
|
470
|
+
}
|
|
471
|
+
let item = stack.pop();
|
|
472
|
+
if (!item) {
|
|
473
|
+
throw new Error(`No items in stack at index ${stackIndex}`);
|
|
474
|
+
}
|
|
475
|
+
this.schedulePersist();
|
|
476
|
+
return item;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
replaceItemInStack(item: StackItem, newItem: StackItem) {
|
|
480
|
+
let stackIndex = item.stackIndex;
|
|
481
|
+
let itemIndex = this._state.stacks[stackIndex].indexOf(item);
|
|
482
|
+
|
|
483
|
+
if (newItem.stackIndex !== stackIndex) {
|
|
484
|
+
// this could be a smell that the stack index should not live in the item
|
|
485
|
+
throw new Error(
|
|
486
|
+
'cannot move stack item to different stack--this can destabilize contained card pointers',
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
this._state.stacks[stackIndex].splice(itemIndex, 1, newItem);
|
|
491
|
+
this.schedulePersist();
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
findCardInStackSafe(
|
|
495
|
+
card: CardDef | string,
|
|
496
|
+
stackIndex: number,
|
|
497
|
+
): StackItem | undefined {
|
|
498
|
+
try {
|
|
499
|
+
return this.findCardInStack(card, stackIndex);
|
|
500
|
+
} catch (err) {
|
|
501
|
+
if (err instanceof Error && err.message.includes('Could not find card')) {
|
|
502
|
+
return undefined;
|
|
503
|
+
}
|
|
504
|
+
throw err;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
findCardInStack(card: CardDef | string, stackIndex: number): StackItem {
|
|
509
|
+
let stack = this._state.stacks[stackIndex];
|
|
510
|
+
if (!stack) {
|
|
511
|
+
throw new Error(`Stack ${stackIndex} does not exist`);
|
|
512
|
+
}
|
|
513
|
+
let cardId = typeof card === 'string' ? card : (card.id as string);
|
|
514
|
+
let normalizedId = cardId?.replace(/\.json$/, '');
|
|
515
|
+
let localId =
|
|
516
|
+
typeof card === 'string' ? undefined : (card as any)[localIdSymbol];
|
|
517
|
+
let item = stack.find(
|
|
518
|
+
(stackItem: StackItem) =>
|
|
519
|
+
stackItem.id === normalizedId ||
|
|
520
|
+
stackItem.id === cardId ||
|
|
521
|
+
(localId && stackItem.id === localId),
|
|
522
|
+
);
|
|
523
|
+
if (!item) {
|
|
524
|
+
throw new Error(
|
|
525
|
+
`Could not find card ${cardId ?? '(unknown id)'} in stack ${stackIndex}`,
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
return item;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// Mutate a stack item's format in place (and any related transient
|
|
532
|
+
// fields) instead of replacing the item. The StackItem class marks
|
|
533
|
+
// format/request/useBaseTemplate as @tracked, so consumers re-render
|
|
534
|
+
// reactively. Crucially, the item's IDENTITY is preserved — Glimmer's
|
|
535
|
+
// {{#each}} keeps the same stack-item component instance, so the
|
|
536
|
+
// CardRenderer (and the user's CardDef component beneath it) are NOT
|
|
537
|
+
// remounted on a format swap. CardDefs whose `static isolated ===
|
|
538
|
+
// static edit` keep DOM state, scroll position, and view-transition
|
|
539
|
+
// continuity across the toggle.
|
|
540
|
+
setItemFormat(
|
|
541
|
+
item: StackItem,
|
|
542
|
+
format: Format,
|
|
543
|
+
opts?: { request?: Deferred<string>; useBaseTemplate?: boolean },
|
|
544
|
+
): void {
|
|
545
|
+
if (item.type === 'file') {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
let formatChanged = item.format !== format;
|
|
549
|
+
item.format = format;
|
|
550
|
+
if (opts && 'request' in opts) item.request = opts.request;
|
|
551
|
+
if (opts && 'useBaseTemplate' in opts)
|
|
552
|
+
item.useBaseTemplate = opts.useBaseTemplate;
|
|
553
|
+
// A format flip is a deliberate user action ("edit this one") —
|
|
554
|
+
// mark it as the most recently interacted item so subsequent
|
|
555
|
+
// keyboard shortcuts target this card, not whatever happened to
|
|
556
|
+
// be opened most recently.
|
|
557
|
+
if (formatChanged) {
|
|
558
|
+
item.markInteracted();
|
|
559
|
+
}
|
|
560
|
+
this.schedulePersist();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
editCardOnStack(
|
|
564
|
+
stackIndex: number,
|
|
565
|
+
card: CardDef,
|
|
566
|
+
opts?: { useBaseTemplate?: boolean },
|
|
567
|
+
): void {
|
|
568
|
+
let item = this.findCardInStack(card, stackIndex);
|
|
569
|
+
if (item.type === 'file') {
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
this.setItemFormat(item, 'edit', {
|
|
573
|
+
request: new Deferred(),
|
|
574
|
+
useBaseTemplate: opts?.useBaseTemplate,
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
viewCardOnStack(
|
|
579
|
+
stackIndex: number,
|
|
580
|
+
card: CardDef,
|
|
581
|
+
opts?: { useBaseTemplate?: boolean },
|
|
582
|
+
): void {
|
|
583
|
+
let item = this.findCardInStack(card, stackIndex);
|
|
584
|
+
if (item.type === 'file') {
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
this.setItemFormat(item, 'isolated', {
|
|
588
|
+
request: new Deferred(),
|
|
589
|
+
useBaseTemplate: opts?.useBaseTemplate,
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
clearStackAndAdd(stackIndex: number, newItem: StackItem) {
|
|
594
|
+
let itemsToPopCount = this._state.stacks[stackIndex].length;
|
|
595
|
+
|
|
596
|
+
for (let i = 0; i < itemsToPopCount; i++) {
|
|
597
|
+
this.popItemFromStack(stackIndex);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
this.addItemToStack(newItem);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
numberOfStacks() {
|
|
604
|
+
return this._state.stacks.length;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
rightMostStack() {
|
|
608
|
+
if (this.numberOfStacks() > 0) {
|
|
609
|
+
return this._state.stacks[this._state.stacks.length - 1];
|
|
610
|
+
}
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
topMostStackItems() {
|
|
615
|
+
return this._state.stacks
|
|
616
|
+
.filter((stack) => stack.length > 0)
|
|
617
|
+
.map((stack) => stack[stack.length - 1]);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
addToHostModeStack(cardId: string) {
|
|
621
|
+
this._state.hostModeStack.push(cardId);
|
|
622
|
+
this.schedulePersist();
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
removeFromHostModeStack(cardId: string) {
|
|
626
|
+
let index = this._state.hostModeStack.findIndex((item) => item === cardId);
|
|
627
|
+
if (index !== -1) {
|
|
628
|
+
this._state.hostModeStack.splice(index, 1);
|
|
629
|
+
this.schedulePersist();
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
get hostModeStack(): string[] {
|
|
634
|
+
return this._state.hostModeStack;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
setHostModePrimaryCard(cardId?: string) {
|
|
638
|
+
if (cardId && !isLocalId(cardId)) {
|
|
639
|
+
this._state.hostModePrimaryCard = cardId.replace(/\.json$/, '');
|
|
640
|
+
} else if (!cardId) {
|
|
641
|
+
this._state.hostModePrimaryCard = null;
|
|
642
|
+
}
|
|
643
|
+
// reset stack when primary card is changed
|
|
644
|
+
this._state.hostModeStack.splice(0, this._state.hostModeStack.length);
|
|
645
|
+
this.schedulePersist();
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
get hostModePrimaryCard(): string | null {
|
|
649
|
+
return this._state.hostModePrimaryCard ?? null;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
private getRealmURLFromItemId(itemId: string): string {
|
|
653
|
+
try {
|
|
654
|
+
return this.realm.realmOf(rri(itemId)) ?? this.realmURL;
|
|
655
|
+
} catch (error) {
|
|
656
|
+
return this.realmURL;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
get isViewingCardInCodeMode() {
|
|
661
|
+
return (
|
|
662
|
+
this._state.submode === Submodes.Code &&
|
|
663
|
+
this.codePathString?.endsWith('.json')
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Determines if we're currently viewing a card in the playground panel
|
|
669
|
+
*/
|
|
670
|
+
get isViewingCardInPlaygroundPanel(): boolean {
|
|
671
|
+
return (
|
|
672
|
+
this._state.submode === Submodes.Code &&
|
|
673
|
+
this.moduleInspectorPanel === 'preview' &&
|
|
674
|
+
!!this.playgroundPanelSelection?.cardId
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Gets the current format being viewed for focus pill display
|
|
680
|
+
*/
|
|
681
|
+
get currentViewingFormat(): Format | undefined {
|
|
682
|
+
if (this.isViewingCardInCodeMode) {
|
|
683
|
+
return this._state.cardPreviewFormat ?? 'isolated';
|
|
684
|
+
} else if (this.isViewingCardInPlaygroundPanel) {
|
|
685
|
+
return this.playgroundPanelSelection?.format ?? 'isolated';
|
|
686
|
+
}
|
|
687
|
+
return undefined;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
getOpenCardIds(): RealmResourceIdentifier[] {
|
|
691
|
+
if (this._state.submode === Submodes.Code) {
|
|
692
|
+
let openCardsInCodeMode: RealmResourceIdentifier[] = [];
|
|
693
|
+
if (this.playgroundPanelSelection) {
|
|
694
|
+
openCardsInCodeMode.push(this.playgroundPanelSelection.cardId);
|
|
695
|
+
}
|
|
696
|
+
// Alternatively we may simply be looking at a card in code mode
|
|
697
|
+
if (this.isViewingCardInCodeMode) {
|
|
698
|
+
let cardId = rri(this.codePathString!.replace(/\.json$/, ''));
|
|
699
|
+
if (!openCardsInCodeMode.includes(cardId)) {
|
|
700
|
+
openCardsInCodeMode.push(cardId);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return openCardsInCodeMode;
|
|
704
|
+
} else {
|
|
705
|
+
// Interact mode
|
|
706
|
+
return this.topMostStackItems()
|
|
707
|
+
.filter((stackItem: StackItem) => stackItem)
|
|
708
|
+
.map((stackItem: StackItem) => stackItem.id)
|
|
709
|
+
.filter(Boolean) as RealmResourceIdentifier[];
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
getOpenCards = restartableTask(async () => {
|
|
714
|
+
let cardIds = this.getOpenCardIds();
|
|
715
|
+
if (!cardIds) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
let cards = (await Promise.all(cardIds.map((id) => this.store.get(id))))
|
|
719
|
+
.filter(Boolean)
|
|
720
|
+
.filter(isCardInstance);
|
|
721
|
+
return cards;
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
get openFileURL(): string | undefined {
|
|
725
|
+
if (this._state.submode === Submodes.Code) {
|
|
726
|
+
return this._state.codePath?.href;
|
|
727
|
+
}
|
|
728
|
+
return undefined;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
stackIsEmpty(stackIndex: number) {
|
|
732
|
+
return this._state.stacks[stackIndex].length === 0;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
shiftStack(stack: StackItem[], destinationIndex: number) {
|
|
736
|
+
let stackItemsCopy = [...stack]; // The actions in the loop are mutating the stack items, so we need to make a copy to make sure to iterate over all items from the original stack
|
|
737
|
+
|
|
738
|
+
stackItemsCopy.forEach((item) => {
|
|
739
|
+
this.popItemFromStack(item.stackIndex);
|
|
740
|
+
this.addItemToStack(
|
|
741
|
+
item.clone({
|
|
742
|
+
stackIndex: destinationIndex,
|
|
743
|
+
}),
|
|
744
|
+
);
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
return this.schedulePersist();
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
async updateSubmode(submode: Submode) {
|
|
751
|
+
this._state.submode = submode;
|
|
752
|
+
this.schedulePersist();
|
|
753
|
+
|
|
754
|
+
if (submode === Submodes.Code) {
|
|
755
|
+
await this.matrixService.activateCodingSkill();
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
async updateModuleInspectorView(view: ModuleInspectorView) {
|
|
760
|
+
this._state.moduleInspector = view;
|
|
761
|
+
this.moduleInspectorHistory[this.state.codePath?.href ?? ''] = view;
|
|
762
|
+
window.localStorage.setItem(
|
|
763
|
+
ModuleInspectorSelections,
|
|
764
|
+
JSON.stringify(this.moduleInspectorHistory),
|
|
765
|
+
);
|
|
766
|
+
this.schedulePersist();
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
async updateCodePathWithSelection({
|
|
770
|
+
codeRef,
|
|
771
|
+
localName,
|
|
772
|
+
fieldName,
|
|
773
|
+
onLocalSelection,
|
|
774
|
+
}: {
|
|
775
|
+
codeRef: CodeRef | undefined;
|
|
776
|
+
localName: string | undefined;
|
|
777
|
+
fieldName: string | undefined;
|
|
778
|
+
onLocalSelection?: (name: string, fieldName?: string) => void;
|
|
779
|
+
}) {
|
|
780
|
+
//moving from one definition to another
|
|
781
|
+
if (codeRef && isResolvedCodeRef(codeRef)) {
|
|
782
|
+
//(possibly) in a different module
|
|
783
|
+
this._state.codeSelection = codeRef.name;
|
|
784
|
+
await this.updateCodePath(codeRef.module);
|
|
785
|
+
} else if (
|
|
786
|
+
codeRef &&
|
|
787
|
+
'type' in codeRef &&
|
|
788
|
+
codeRef.type === 'fieldOf' &&
|
|
789
|
+
'card' in codeRef &&
|
|
790
|
+
isResolvedCodeRef(codeRef.card)
|
|
791
|
+
) {
|
|
792
|
+
this._state.fieldSelection = codeRef.field;
|
|
793
|
+
this._state.codeSelection = codeRef.card.name;
|
|
794
|
+
await this.updateCodePath(codeRef.card.module);
|
|
795
|
+
} else if (localName && onLocalSelection) {
|
|
796
|
+
//in the same module
|
|
797
|
+
this._state.codeSelection = localName;
|
|
798
|
+
this._state.fieldSelection = fieldName;
|
|
799
|
+
this.schedulePersist();
|
|
800
|
+
onLocalSelection(localName, fieldName);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
get codePathRelativeToRealm() {
|
|
805
|
+
if (this._state.codePath && this.realmURL) {
|
|
806
|
+
let realmPath = new RealmPaths(new URL(this.realmURL));
|
|
807
|
+
|
|
808
|
+
if (realmPath.inRealm(this._state.codePath)) {
|
|
809
|
+
try {
|
|
810
|
+
return realmPath.local(this._state.codePath!);
|
|
811
|
+
} catch (err: any) {
|
|
812
|
+
if (err.status === 404) {
|
|
813
|
+
return undefined;
|
|
814
|
+
}
|
|
815
|
+
throw err;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return undefined;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
get codePathString(): RealmResourceIdentifier | undefined {
|
|
824
|
+
return this._state.codePath?.toString() as
|
|
825
|
+
| RealmResourceIdentifier
|
|
826
|
+
| undefined;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
onFileSelected = async (entryPath: LocalPath) => {
|
|
830
|
+
let fileUrl = new RealmPaths(new URL(this.realmURL)).fileURL(entryPath);
|
|
831
|
+
await this.updateCodePath(fileUrl);
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
async updateCodePath(
|
|
835
|
+
codePath: RealmResourceIdentifier | URL | null,
|
|
836
|
+
moduleInspectorView?: ModuleInspectorView,
|
|
837
|
+
) {
|
|
838
|
+
let codePathURL =
|
|
839
|
+
typeof codePath === 'string' ? cardIdToURL(codePath) : codePath;
|
|
840
|
+
let canonicalCodePath = await this.determineCanonicalCodePath(codePathURL);
|
|
841
|
+
this._state.codePath = canonicalCodePath;
|
|
842
|
+
this.updateOpenDirsForNestedPath();
|
|
843
|
+
this.schedulePersist();
|
|
844
|
+
|
|
845
|
+
moduleInspectorView =
|
|
846
|
+
moduleInspectorView ??
|
|
847
|
+
this.moduleInspectorHistory[canonicalCodePath?.href ?? ''] ??
|
|
848
|
+
DEFAULT_MODULE_INSPECTOR_VIEW;
|
|
849
|
+
|
|
850
|
+
this.updateModuleInspectorView(moduleInspectorView);
|
|
851
|
+
|
|
852
|
+
this.specPanelService.setSelection(null);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
persistModuleInspectorView(
|
|
856
|
+
codePath: string | null,
|
|
857
|
+
moduleInspector: ModuleInspectorView,
|
|
858
|
+
) {
|
|
859
|
+
if (codePath) {
|
|
860
|
+
this.moduleInspectorHistory[codePath] = moduleInspector;
|
|
861
|
+
window.localStorage.setItem(
|
|
862
|
+
ModuleInspectorSelections,
|
|
863
|
+
JSON.stringify(this.moduleInspectorHistory),
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
private async determineCanonicalCodePath(codePath: URL | null) {
|
|
869
|
+
if (!codePath) {
|
|
870
|
+
return codePath;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
let response;
|
|
874
|
+
try {
|
|
875
|
+
response = await this.network.authedFetch(codePath, {
|
|
876
|
+
method: 'HEAD',
|
|
877
|
+
headers: { Accept: SupportedMimeType.CardSource },
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
if (response.ok) {
|
|
881
|
+
return new URL(response.url);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
return codePath;
|
|
885
|
+
} catch (_e) {
|
|
886
|
+
return codePath;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
replaceCodePath(codePath: URL | null) {
|
|
891
|
+
// replace history explicitly
|
|
892
|
+
// typically used when, serving a redirect in the code path
|
|
893
|
+
// solve UX issues with back button referring back to request url of redirect
|
|
894
|
+
// when it should refer back to the previous code path
|
|
895
|
+
this._state.codePath = codePath;
|
|
896
|
+
this.router.replaceWith('index-root', {
|
|
897
|
+
queryParams: {
|
|
898
|
+
operatorModeState: this.serialize(),
|
|
899
|
+
},
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
setCardTitle(url: string, title: string) {
|
|
904
|
+
this.setCardTitleTask.perform(url, title);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// we use a task to organize simultaneous updates, otherwise you may get error
|
|
908
|
+
// around updating a value previously used in a computation
|
|
909
|
+
private setCardTitleTask = task(async (url: string, title: string) => {
|
|
910
|
+
await Promise.resolve(); // wait 1 micro task
|
|
911
|
+
this.cardTitles.set(url, title);
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
@cached
|
|
915
|
+
get title() {
|
|
916
|
+
if (this._state.submode === Submodes.Code) {
|
|
917
|
+
return `${this.codePathRelativeToRealm} in ${
|
|
918
|
+
this.realm.info(this.realmURL).name
|
|
919
|
+
}`;
|
|
920
|
+
} else {
|
|
921
|
+
let itemForTitle = this.topMostStackItems().pop(); // top-most card of right stack
|
|
922
|
+
return (
|
|
923
|
+
(itemForTitle?.id ? this.cardTitles.get(itemForTitle.id) : 'Boxel') ??
|
|
924
|
+
'Boxel'
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
private updateOpenDirsForNestedPath() {
|
|
930
|
+
let localPath = this.codePathRelativeToRealm;
|
|
931
|
+
|
|
932
|
+
if (localPath) {
|
|
933
|
+
let segments = localPath.split('/').slice(0, -1).filter(Boolean);
|
|
934
|
+
let accumulator: string[] = [];
|
|
935
|
+
|
|
936
|
+
for (let segment of segments) {
|
|
937
|
+
accumulator.push(segment);
|
|
938
|
+
let dirPath = `${accumulator.join('/')}/`;
|
|
939
|
+
|
|
940
|
+
if (!this.currentRealmOpenDirs.includes(dirPath)) {
|
|
941
|
+
this.toggleOpenDir(dirPath);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
get currentRealmOpenDirs() {
|
|
948
|
+
if (this.realmURL) {
|
|
949
|
+
let currentRealmOpenDirs = this.openDirs.get(this.realmURL);
|
|
950
|
+
|
|
951
|
+
if (currentRealmOpenDirs) {
|
|
952
|
+
return currentRealmOpenDirs;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
return new TrackedArray([]);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
updateFileView(fileView: FileView) {
|
|
960
|
+
this._state.fileView = fileView;
|
|
961
|
+
this.schedulePersist();
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
updateCardPreviewFormat(format: Format) {
|
|
965
|
+
this._state.cardPreviewFormat = format;
|
|
966
|
+
this.schedulePersist();
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
clearStacks() {
|
|
970
|
+
this._state.stacks.splice(0);
|
|
971
|
+
this.schedulePersist();
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
// when a stack item's card has been saved we need to update the URL to reflect the saved card's remote ID
|
|
975
|
+
// TODO make test for reloading after card has been saved
|
|
976
|
+
handleCardIdAssignment(localId: string) {
|
|
977
|
+
if (
|
|
978
|
+
this._state.stacks.find((stack) =>
|
|
979
|
+
stack.find((item) => item.id === localId),
|
|
980
|
+
)
|
|
981
|
+
) {
|
|
982
|
+
this.schedulePersist();
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
private schedulePersist() {
|
|
987
|
+
// When multiple stack manipulations are bunched together in a loop, for example when closing multiple cards in a loop,
|
|
988
|
+
// we get into a async race condition where the change to cardController.operatorModeState will reload the route and
|
|
989
|
+
// restore the state from the query param in a way that is out of sync with the state in the service. To avoid this,
|
|
990
|
+
// we do the change to the query param only after all modifications to the state have been rendered.
|
|
991
|
+
scheduleOnce('afterRender', this, this.persist);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
private persist() {
|
|
995
|
+
if (this.isDestroyed) {
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
this.operatorModeController.operatorModeState = this.serialize();
|
|
999
|
+
// This sets the title of the document for it's appearance in the browser
|
|
1000
|
+
// history (which needs to happen after the history pushState)--the
|
|
1001
|
+
// afterRender is the perfect place for this
|
|
1002
|
+
document.title = this.title;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
// Serialized POJO version of state, with only cards that have been saved.
|
|
1006
|
+
// The state can have cards that have not been saved yet, for example when
|
|
1007
|
+
// clicking on "Create New" in linked card editor. Here we want to draw a boundary
|
|
1008
|
+
// between navigable states in the query parameter
|
|
1009
|
+
rawStateWithSavedCardsOnly() {
|
|
1010
|
+
let trail = [
|
|
1011
|
+
this._state.hostModePrimaryCard,
|
|
1012
|
+
...this._state.hostModeStack.map((item) => item),
|
|
1013
|
+
].filter(Boolean) as string[];
|
|
1014
|
+
let state: SerializedState = {
|
|
1015
|
+
stacks: [],
|
|
1016
|
+
submode: this._state.submode,
|
|
1017
|
+
codePath: this._state.codePath?.toString(),
|
|
1018
|
+
trail,
|
|
1019
|
+
fileView: this._state.fileView?.toString() as FileView,
|
|
1020
|
+
openDirs: Object.fromEntries(this._state.openDirs.entries()),
|
|
1021
|
+
codeSelection: this._state.codeSelection,
|
|
1022
|
+
fieldSelection: this._state.fieldSelection,
|
|
1023
|
+
moduleInspector: this._state.moduleInspector,
|
|
1024
|
+
cardPreviewFormat: this._state.cardPreviewFormat,
|
|
1025
|
+
};
|
|
1026
|
+
if (this._state.aiAssistantOpen) {
|
|
1027
|
+
state.aiAssistantOpen = this._state.aiAssistantOpen;
|
|
1028
|
+
}
|
|
1029
|
+
if (this._state.workspaceChooserOpened) {
|
|
1030
|
+
state.workspaceChooserOpened = this._state.workspaceChooserOpened;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
for (let stack of this._state.stacks) {
|
|
1034
|
+
let serializedStack: SerializedStack = [];
|
|
1035
|
+
for (let item of stack) {
|
|
1036
|
+
if (
|
|
1037
|
+
item.format !== 'isolated' &&
|
|
1038
|
+
item.format !== 'edit' &&
|
|
1039
|
+
item.format !== 'head'
|
|
1040
|
+
) {
|
|
1041
|
+
throw new Error(`Unknown format for card on stack ${item.format}`);
|
|
1042
|
+
}
|
|
1043
|
+
if (item.id) {
|
|
1044
|
+
let instance =
|
|
1045
|
+
this.store.peek(item.id) ??
|
|
1046
|
+
this.store.peek(item.id, { type: 'file-meta' });
|
|
1047
|
+
if (!isLocalId(item.id) || instance?.id) {
|
|
1048
|
+
serializedStack.push({
|
|
1049
|
+
id: instance?.id ?? item.id,
|
|
1050
|
+
format: item.format,
|
|
1051
|
+
type: item.type === 'card' ? undefined : item.type,
|
|
1052
|
+
useBaseTemplate: item.useBaseTemplate ?? undefined,
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
state.stacks.push(serializedStack);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
let expandedStackItem = this.serializedExpandedStackItem;
|
|
1061
|
+
if (expandedStackItem) {
|
|
1062
|
+
state.expandedStackItem = expandedStackItem;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
return state;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// Stringified JSON version of state, with only cards that have been saved, used for the query param
|
|
1069
|
+
serialize(): string {
|
|
1070
|
+
return stringify(this.rawStateWithSavedCardsOnly())!;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
createStackItem(
|
|
1074
|
+
id: string,
|
|
1075
|
+
stackIndex: number,
|
|
1076
|
+
format: 'isolated' | 'edit' = 'isolated',
|
|
1077
|
+
relationshipContext?: {
|
|
1078
|
+
fieldName?: string;
|
|
1079
|
+
fieldType?: 'linksTo' | 'linksToMany';
|
|
1080
|
+
},
|
|
1081
|
+
type?: StackItemType,
|
|
1082
|
+
) {
|
|
1083
|
+
let stackItem = new StackItem({
|
|
1084
|
+
id,
|
|
1085
|
+
stackIndex,
|
|
1086
|
+
format,
|
|
1087
|
+
relationshipContext,
|
|
1088
|
+
type,
|
|
1089
|
+
});
|
|
1090
|
+
return stackItem;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// Deserialize a stringified JSON version of OperatorModeState into a Glimmer tracked object
|
|
1094
|
+
// so that templates can react to changes in stacks and their items
|
|
1095
|
+
deserialize(rawState: SerializedState): OperatorModeState {
|
|
1096
|
+
this.expandedStackItems.clear();
|
|
1097
|
+
|
|
1098
|
+
let openDirs = new TrackedMap<string, string[]>(
|
|
1099
|
+
Object.entries(rawState.openDirs ?? {}).map(([realmURL, dirs]) => [
|
|
1100
|
+
realmURL,
|
|
1101
|
+
new TrackedArray(dirs),
|
|
1102
|
+
]),
|
|
1103
|
+
);
|
|
1104
|
+
|
|
1105
|
+
let newState: OperatorModeState = new TrackedObject({
|
|
1106
|
+
stacks: new TrackedArray([]),
|
|
1107
|
+
submode: rawState.submode ?? Submodes.Interact,
|
|
1108
|
+
codePath: rawState.codePath ? new URL(rawState.codePath) : null,
|
|
1109
|
+
hostModePrimaryCard: rawState.trail?.[0]?.replace(/\.json$/, '') ?? null,
|
|
1110
|
+
hostModeStack: new TrackedArray(
|
|
1111
|
+
rawState.trail
|
|
1112
|
+
?.slice(1, rawState.trail?.length)
|
|
1113
|
+
.map((item) => item.replace(/\.json$/, '')) ?? [],
|
|
1114
|
+
),
|
|
1115
|
+
fileView: rawState.fileView ?? 'inspector',
|
|
1116
|
+
openDirs,
|
|
1117
|
+
codeSelection: rawState.codeSelection,
|
|
1118
|
+
fieldSelection: rawState.fieldSelection,
|
|
1119
|
+
aiAssistantOpen:
|
|
1120
|
+
rawState.aiAssistantOpen ?? readPersistedAiAssistantOpen(),
|
|
1121
|
+
moduleInspector:
|
|
1122
|
+
rawState.moduleInspector ?? DEFAULT_MODULE_INSPECTOR_VIEW,
|
|
1123
|
+
cardPreviewFormat: rawState.cardPreviewFormat ?? 'isolated',
|
|
1124
|
+
workspaceChooserOpened: rawState.workspaceChooserOpened ?? false,
|
|
1125
|
+
});
|
|
1126
|
+
|
|
1127
|
+
if (rawState.codePath && rawState.moduleInspector) {
|
|
1128
|
+
this.persistModuleInspectorView(
|
|
1129
|
+
rawState.codePath,
|
|
1130
|
+
rawState.moduleInspector,
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
let stackIndex = 0;
|
|
1135
|
+
for (let stack of rawState.stacks) {
|
|
1136
|
+
let newStack: Stack = new TrackedArray([]);
|
|
1137
|
+
for (let item of stack) {
|
|
1138
|
+
let { format } = item;
|
|
1139
|
+
newStack.push(
|
|
1140
|
+
new StackItem({
|
|
1141
|
+
id: item.id,
|
|
1142
|
+
format,
|
|
1143
|
+
stackIndex,
|
|
1144
|
+
type: item.type,
|
|
1145
|
+
useBaseTemplate: item.useBaseTemplate,
|
|
1146
|
+
}),
|
|
1147
|
+
);
|
|
1148
|
+
}
|
|
1149
|
+
newState.stacks.push(newStack);
|
|
1150
|
+
stackIndex++;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
let expandedStackItem = rawState.expandedStackItem;
|
|
1154
|
+
if (expandedStackItem) {
|
|
1155
|
+
let stack = newState.stacks[expandedStackItem.stackIndex];
|
|
1156
|
+
let item = stack?.find(
|
|
1157
|
+
(candidate) => candidate.id === expandedStackItem.id,
|
|
1158
|
+
);
|
|
1159
|
+
if (item) {
|
|
1160
|
+
this.expandedStackItems.set(item.instanceId, true);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
return newState;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
private get serializedExpandedStackItem():
|
|
1168
|
+
| SerializedExpandedStackItem
|
|
1169
|
+
| undefined {
|
|
1170
|
+
for (let [stackIndex, stack] of this._state.stacks.entries()) {
|
|
1171
|
+
for (let item of stack) {
|
|
1172
|
+
if (item.id && this.expandedStackItems.has(item.instanceId)) {
|
|
1173
|
+
return {
|
|
1174
|
+
id: item.id,
|
|
1175
|
+
stackIndex,
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
return undefined;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
get openDirs() {
|
|
1185
|
+
return this._state.openDirs ?? new TrackedMap();
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
toggleOpenDir = (entryPath: string): void => {
|
|
1189
|
+
if (!this.realmURL) {
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
let dirPath = normalizeDirPath(entryPath);
|
|
1194
|
+
let dirs = this.currentRealmOpenDirs.slice();
|
|
1195
|
+
let index = dirs.indexOf(dirPath);
|
|
1196
|
+
|
|
1197
|
+
if (index !== -1) {
|
|
1198
|
+
dirs.splice(index, 1);
|
|
1199
|
+
} else {
|
|
1200
|
+
dirs.push(dirPath);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
this.openDirs.set(this.realmURL, new TrackedArray(dirs));
|
|
1204
|
+
this.schedulePersist();
|
|
1205
|
+
};
|
|
1206
|
+
|
|
1207
|
+
private get readyFile() {
|
|
1208
|
+
if (isReady(this.openFile.current)) {
|
|
1209
|
+
return this.openFile.current;
|
|
1210
|
+
}
|
|
1211
|
+
throw new Error(
|
|
1212
|
+
`cannot access file contents ${this._state.codePath} before file is open`,
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
get openFileIsReady() {
|
|
1217
|
+
return isReady(this.openFile.current);
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
@cached
|
|
1221
|
+
get realmURL(): string {
|
|
1222
|
+
let { submode } = this._state;
|
|
1223
|
+
if (submode === Submodes.Code) {
|
|
1224
|
+
if (isReady(this.openFile.current)) {
|
|
1225
|
+
return this.readyFile.realmURL;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
// For interact mode, the idea of "current realm" is a bit abstract. the
|
|
1230
|
+
// realm background that you see in interact mode is the realm of the
|
|
1231
|
+
// bottom-most card in the stack. however you can have cards of differing
|
|
1232
|
+
// realms in the same stack and keep in mind you can have multiple stacks...
|
|
1233
|
+
if (submode === Submodes.Interact) {
|
|
1234
|
+
// Precedence rules for determining "current realm" for READ purposes:
|
|
1235
|
+
// 1. cardURL of the index card to determine current realm
|
|
1236
|
+
// 2. If no index card available, the realm of the top-most card
|
|
1237
|
+
let stack = this.rightMostStack(); // using right-most stack
|
|
1238
|
+
if (stack) {
|
|
1239
|
+
let cardId =
|
|
1240
|
+
stack[0]?.id &&
|
|
1241
|
+
this.realmServer.availableRealmIndexCardIds.includes(stack[0]?.id)
|
|
1242
|
+
? stack[0].id
|
|
1243
|
+
: stack[stack.length - 1]?.id;
|
|
1244
|
+
if (cardId) {
|
|
1245
|
+
let realm = this.realm.url(cardId);
|
|
1246
|
+
if (realm) {
|
|
1247
|
+
return realm;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
// For host mode, determine realm from hostModePrimaryCard using availableRealmIndexCardIds
|
|
1254
|
+
if (submode === Submodes.Host) {
|
|
1255
|
+
// Check if hostModePrimaryCard is an available realm index card
|
|
1256
|
+
// If hostModePrimaryCard is not an index card, try to find the realm from the card's realm
|
|
1257
|
+
if (this._state.hostModePrimaryCard) {
|
|
1258
|
+
let cardId = this._state.hostModePrimaryCard.replace(/\.json$/, '');
|
|
1259
|
+
let realm = this.realm.url(cardId);
|
|
1260
|
+
if (realm) {
|
|
1261
|
+
return realm;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
if (this.cachedRealmURL) {
|
|
1267
|
+
return this.cachedRealmURL.href;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
return this.realm.defaultReadableRealm.path;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
get currentRealmInfo() {
|
|
1274
|
+
return this.realm.info(this.realmURL);
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
getWritableRealmURL = (preferredURLs: string[] = []) => {
|
|
1278
|
+
// Optional `preferredURLs` argument with highest priority with fallback options below
|
|
1279
|
+
// Precedence rules for determining "current realm" for WRITE purposes:
|
|
1280
|
+
// 1. cardURL of the index card to determine current realm
|
|
1281
|
+
// 2. If no index card available, the realm of the top-most card if the realm is writable.
|
|
1282
|
+
// 3. Otherwise, fallback to the last opened writable realm, especially if the opening click is from dashboard.
|
|
1283
|
+
let urlsToCheck = [
|
|
1284
|
+
...preferredURLs,
|
|
1285
|
+
this.realmURL,
|
|
1286
|
+
this.cachedRealmURL?.href,
|
|
1287
|
+
].filter(Boolean) as string[];
|
|
1288
|
+
|
|
1289
|
+
let foundURL = urlsToCheck.find((url) => this.realm.canWrite(url));
|
|
1290
|
+
|
|
1291
|
+
if (foundURL) {
|
|
1292
|
+
return new URL(this.realm.url(foundURL)!);
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
if (this.realm.defaultWritableRealm) {
|
|
1296
|
+
return new URL(this.realm.defaultWritableRealm.path);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
return undefined; // no writable realm found
|
|
1300
|
+
};
|
|
1301
|
+
|
|
1302
|
+
subscribeToOpenFileStateChanges(subscriber: OpenFileSubscriber) {
|
|
1303
|
+
this.openFileSubscribers.push(subscriber);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
unsubscribeFromOpenFileStateChanges(subscriber: OpenFileSubscriber) {
|
|
1307
|
+
let subscriberIndex = this.openFileSubscribers.indexOf(subscriber);
|
|
1308
|
+
|
|
1309
|
+
if (subscriberIndex > -1) {
|
|
1310
|
+
this.openFileSubscribers.splice(subscriberIndex, 1);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
openFile = maybe(this, (context: object) => {
|
|
1315
|
+
let codePath = this._state.codePath;
|
|
1316
|
+
|
|
1317
|
+
if (!codePath) {
|
|
1318
|
+
return undefined;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
return file(context, () => ({
|
|
1322
|
+
url: codePath!.href,
|
|
1323
|
+
onStateChange: (state: FileResource['state']) => {
|
|
1324
|
+
if (state === 'ready') {
|
|
1325
|
+
this.cachedRealmURL = new URL(this.readyFile.realmURL);
|
|
1326
|
+
this.updateOpenDirsForNestedPath();
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
this.openFileSubscribers.forEach((subscriber) =>
|
|
1330
|
+
subscriber.onStateChange(state),
|
|
1331
|
+
);
|
|
1332
|
+
},
|
|
1333
|
+
onRedirect: (url: string) => {
|
|
1334
|
+
if (!url) {
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
this.replaceCodePath(new URL(url));
|
|
1338
|
+
},
|
|
1339
|
+
}));
|
|
1340
|
+
});
|
|
1341
|
+
|
|
1342
|
+
openCardInInteractMode(
|
|
1343
|
+
id: string,
|
|
1344
|
+
format: Format = 'isolated',
|
|
1345
|
+
type: StackItemType = 'card',
|
|
1346
|
+
) {
|
|
1347
|
+
this.clearStacks();
|
|
1348
|
+
// Determine realm URL. If id is a localId, look up the instance in the store to read its realm.
|
|
1349
|
+
let realmHref: string | undefined;
|
|
1350
|
+
if (isLocalId(id)) {
|
|
1351
|
+
let instance = this.store.peek(id);
|
|
1352
|
+
if (instance && isCardInstance(instance)) {
|
|
1353
|
+
realmHref = (instance as any)[realmURLSymbol]?.href;
|
|
1354
|
+
}
|
|
1355
|
+
} else {
|
|
1356
|
+
realmHref = this.realm.url(id) ?? undefined;
|
|
1357
|
+
}
|
|
1358
|
+
if (!realmHref) {
|
|
1359
|
+
// Fallback to default readable realm so UI still opens; this should be unusual.
|
|
1360
|
+
realmHref = this.realm.defaultReadableRealm.path;
|
|
1361
|
+
}
|
|
1362
|
+
if (!realmHref.endsWith('/')) {
|
|
1363
|
+
realmHref = realmHref + '/';
|
|
1364
|
+
}
|
|
1365
|
+
let indexItem = new StackItem({
|
|
1366
|
+
id: `${realmHref}index`,
|
|
1367
|
+
stackIndex: 0,
|
|
1368
|
+
format: 'isolated',
|
|
1369
|
+
type: 'card',
|
|
1370
|
+
});
|
|
1371
|
+
let newItem = new StackItem({
|
|
1372
|
+
id, // keep provided id (may be localId) so later replacement on save works
|
|
1373
|
+
stackIndex: 0,
|
|
1374
|
+
format,
|
|
1375
|
+
type,
|
|
1376
|
+
});
|
|
1377
|
+
this.addItemToStack(indexItem);
|
|
1378
|
+
this.addItemToStack(newItem);
|
|
1379
|
+
this.updateSubmode(Submodes.Interact);
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
openWorkspaceChooser() {
|
|
1383
|
+
this._state.workspaceChooserOpened = true;
|
|
1384
|
+
this.schedulePersist();
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
closeWorkspaceChooser() {
|
|
1388
|
+
this._state.workspaceChooserOpened = false;
|
|
1389
|
+
this.schedulePersist();
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
openWorkspace = async (realmUrl: string) => {
|
|
1393
|
+
// Ensure realmUrl has a trailing slash
|
|
1394
|
+
if (!realmUrl.endsWith('/')) {
|
|
1395
|
+
realmUrl = realmUrl + '/';
|
|
1396
|
+
}
|
|
1397
|
+
let id = rri(`${realmUrl}index`);
|
|
1398
|
+
let stackItem = new StackItem({
|
|
1399
|
+
id,
|
|
1400
|
+
format: 'isolated',
|
|
1401
|
+
stackIndex: 0,
|
|
1402
|
+
type: 'card',
|
|
1403
|
+
});
|
|
1404
|
+
this.clearStacks();
|
|
1405
|
+
this.addItemToStack(stackItem);
|
|
1406
|
+
|
|
1407
|
+
let lastOpenedFile = this.recentFilesService.recentFiles.find(
|
|
1408
|
+
(file: RecentFile) => file.realmURL.href === realmUrl,
|
|
1409
|
+
);
|
|
1410
|
+
await this.updateCodePath(
|
|
1411
|
+
lastOpenedFile
|
|
1412
|
+
? new URL(`${lastOpenedFile.realmURL}${lastOpenedFile.filePath}`)
|
|
1413
|
+
: id,
|
|
1414
|
+
);
|
|
1415
|
+
this.updateSubmode(Submodes.Interact);
|
|
1416
|
+
|
|
1417
|
+
this._state.workspaceChooserOpened = false;
|
|
1418
|
+
this.cachedRealmURL = new URL(realmUrl);
|
|
1419
|
+
};
|
|
1420
|
+
|
|
1421
|
+
get workspaceChooserOpened() {
|
|
1422
|
+
return this.state.workspaceChooserOpened ?? false;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
set workspaceChooserOpened(workspaceChooserOpened: boolean) {
|
|
1426
|
+
this._state.workspaceChooserOpened = workspaceChooserOpened;
|
|
1427
|
+
this.schedulePersist();
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
// Operator mode state is persisted in a query param, which lives in the index controller
|
|
1431
|
+
get operatorModeController(): IndexController {
|
|
1432
|
+
let controller = getOwner(this)!.lookup(
|
|
1433
|
+
'controller:index',
|
|
1434
|
+
) as IndexController;
|
|
1435
|
+
|
|
1436
|
+
return controller;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
get moduleInspectorPanel() {
|
|
1440
|
+
return (
|
|
1441
|
+
JSON.parse(
|
|
1442
|
+
window.localStorage.getItem(ModuleInspectorSelections) ?? '{}',
|
|
1443
|
+
)[this.codePathString ?? ''] ?? DEFAULT_MODULE_INSPECTOR_VIEW
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
get playgroundPanelSelection(): PlaygroundSelection | undefined {
|
|
1448
|
+
if (this.moduleInspectorPanel === 'preview') {
|
|
1449
|
+
let playgroundSelections =
|
|
1450
|
+
this.playgroundPanelService.playgroundSelections ?? {};
|
|
1451
|
+
if (this.codePathString && playgroundSelections[this.codePathString]) {
|
|
1452
|
+
return playgroundSelections[this.codePathString];
|
|
1453
|
+
}
|
|
1454
|
+
let selectedCodeRefUrl = this.codeSemanticsService.selectedCodeRef
|
|
1455
|
+
? internalKeyFor(this.codeSemanticsService.selectedCodeRef!, undefined)
|
|
1456
|
+
: null;
|
|
1457
|
+
if (selectedCodeRefUrl && playgroundSelections[selectedCodeRefUrl]) {
|
|
1458
|
+
return playgroundSelections[selectedCodeRefUrl];
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
return undefined;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
async getSummaryForAIBot(
|
|
1465
|
+
openCardIdsSet: Set<RealmResourceIdentifier> = new Set([
|
|
1466
|
+
...this.getOpenCardIds(),
|
|
1467
|
+
]),
|
|
1468
|
+
): Promise<BoxelContext> {
|
|
1469
|
+
let codeMode: BoxelContext['codeMode'] = undefined;
|
|
1470
|
+
if (this._state.workspaceChooserOpened) {
|
|
1471
|
+
let userWorkspaces = this.realmServer.userRealmIdentifiers.map((url) => ({
|
|
1472
|
+
url,
|
|
1473
|
+
name: this.realm.info(url).name,
|
|
1474
|
+
type: 'user-workspace' as const,
|
|
1475
|
+
}));
|
|
1476
|
+
let catalogWorkspaces = this.realmServer.catalogRealmIdentifiers.map(
|
|
1477
|
+
(url) => ({
|
|
1478
|
+
url,
|
|
1479
|
+
name: this.realm.info(url).name,
|
|
1480
|
+
type: 'catalog-workspace' as const,
|
|
1481
|
+
}),
|
|
1482
|
+
);
|
|
1483
|
+
let result: BoxelContext = {
|
|
1484
|
+
agentId: this.matrixService.agentId,
|
|
1485
|
+
submode: 'workspace-chooser',
|
|
1486
|
+
debug: this.operatorModeController.debug,
|
|
1487
|
+
openCardIds: [],
|
|
1488
|
+
workspaces: [...userWorkspaces, ...catalogWorkspaces],
|
|
1489
|
+
};
|
|
1490
|
+
let errorsDisplayed = this.errorDisplay.getDisplayedErrors();
|
|
1491
|
+
if (errorsDisplayed.length) {
|
|
1492
|
+
result.errorsDisplayed = errorsDisplayed;
|
|
1493
|
+
}
|
|
1494
|
+
return result;
|
|
1495
|
+
}
|
|
1496
|
+
if (this._state.submode === Submodes.Code) {
|
|
1497
|
+
codeMode = {
|
|
1498
|
+
currentFile: this.codePathString,
|
|
1499
|
+
};
|
|
1500
|
+
|
|
1501
|
+
// Add selection range information when in code mode
|
|
1502
|
+
let selection = this.monacoService.getSelection();
|
|
1503
|
+
if (selection) {
|
|
1504
|
+
codeMode.selectionRange = {
|
|
1505
|
+
startLine: selection.startLineNumber,
|
|
1506
|
+
startColumn: selection.startColumn,
|
|
1507
|
+
endLine: selection.endLineNumber,
|
|
1508
|
+
endColumn: selection.endColumn,
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
if (this.isViewingCardInCodeMode) {
|
|
1513
|
+
codeMode.moduleInspectorPanel = 'preview';
|
|
1514
|
+
codeMode.previewPanelSelection = {
|
|
1515
|
+
cardId: rri(this.codePathString!.replace(/\.json$/, '')),
|
|
1516
|
+
format: this.currentViewingFormat ?? 'isolated',
|
|
1517
|
+
};
|
|
1518
|
+
} else {
|
|
1519
|
+
codeMode.moduleInspectorPanel = this.moduleInspectorPanel;
|
|
1520
|
+
codeMode.previewPanelSelection = this.playgroundPanelSelection
|
|
1521
|
+
? {
|
|
1522
|
+
cardId: this.playgroundPanelSelection.cardId,
|
|
1523
|
+
format: this.currentViewingFormat!,
|
|
1524
|
+
}
|
|
1525
|
+
: undefined;
|
|
1526
|
+
codeMode.selectedCodeRef = this.codeSemanticsService.selectedCodeRef;
|
|
1527
|
+
codeMode.inheritanceChain =
|
|
1528
|
+
await this.codeSemanticsService.getInheritanceChain();
|
|
1529
|
+
|
|
1530
|
+
// Include active spec ID when spec pane is active
|
|
1531
|
+
if (
|
|
1532
|
+
this.moduleInspectorPanel === 'spec' &&
|
|
1533
|
+
this.specPanelService.specSelection
|
|
1534
|
+
) {
|
|
1535
|
+
codeMode.activeSpecId = this.specPanelService.specSelection;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
let openCardIds = this.makeRemoteIdsList([...openCardIdsSet]);
|
|
1541
|
+
let realmUrl = this.realmURL;
|
|
1542
|
+
let realmPermissions = {
|
|
1543
|
+
canRead: this.realm.canRead(realmUrl),
|
|
1544
|
+
canWrite: this.realm.canWrite(realmUrl),
|
|
1545
|
+
};
|
|
1546
|
+
|
|
1547
|
+
let result: BoxelContext = {
|
|
1548
|
+
agentId: this.matrixService.agentId,
|
|
1549
|
+
submode: this._state.submode,
|
|
1550
|
+
debug: this.operatorModeController.debug,
|
|
1551
|
+
openCardIds,
|
|
1552
|
+
realmUrl,
|
|
1553
|
+
realmPermissions,
|
|
1554
|
+
codeMode,
|
|
1555
|
+
};
|
|
1556
|
+
let errorsDisplayed = this.errorDisplay.getDisplayedErrors();
|
|
1557
|
+
if (errorsDisplayed.length) {
|
|
1558
|
+
result.errorsDisplayed = errorsDisplayed;
|
|
1559
|
+
}
|
|
1560
|
+
return result;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
private makeRemoteIdsList(
|
|
1564
|
+
ids: (RealmResourceIdentifier | undefined)[],
|
|
1565
|
+
): RealmResourceIdentifier[] {
|
|
1566
|
+
return ids
|
|
1567
|
+
.map((id) => {
|
|
1568
|
+
if (!id) {
|
|
1569
|
+
return undefined;
|
|
1570
|
+
}
|
|
1571
|
+
if (isLocalId(id)) {
|
|
1572
|
+
let maybeInstance = this.store.peek(id);
|
|
1573
|
+
if (
|
|
1574
|
+
maybeInstance &&
|
|
1575
|
+
isCardInstance(maybeInstance) &&
|
|
1576
|
+
maybeInstance.id
|
|
1577
|
+
) {
|
|
1578
|
+
return maybeInstance.id;
|
|
1579
|
+
} else {
|
|
1580
|
+
return undefined;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return id;
|
|
1584
|
+
})
|
|
1585
|
+
.filter(Boolean) as RealmResourceIdentifier[];
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
declare module '@ember/service' {
|
|
1590
|
+
interface Registry {
|
|
1591
|
+
'operator-mode-state-service': OperatorModeStateService;
|
|
1592
|
+
}
|
|
1593
|
+
}
|