@jini-ai/ui 0.6.15-rc.2 → 0.6.16

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.
Files changed (227) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/browser/useDismissOnOutsideOrEscape.js +1 -1
  3. package/dist/browser/useGlobalKeydown.js +2 -2
  4. package/dist/browser/useModalWindowDragGuard.js +1 -1
  5. package/dist/core/theme/css-name.d.ts +3 -0
  6. package/dist/core/theme/css-name.js +5 -0
  7. package/dist/core/theme/stylesheet.js +2 -1
  8. package/dist/core/theme/validation.js +15 -4
  9. package/dist/core.d.ts +1 -1
  10. package/dist/core.js +1 -1
  11. package/dist/features/about/rules.js +2 -1
  12. package/dist/features/admin-widgets/components/InfoTip.hooks.js +22 -12
  13. package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.js +1 -1
  14. package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.js +1 -1
  15. package/dist/features/admin-widgets/components/SeeMore/SeeMore.hooks.js +2 -2
  16. package/dist/features/admin-widgets/components/SeeMore/SeeMore.js +4 -2
  17. package/dist/features/admin-widgets/components/Select/Select.hooks.js +2 -1
  18. package/dist/features/admin-widgets/components/Select/Select.js +2 -1
  19. package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.js +4 -2
  20. package/dist/features/admin-widgets/components/useDebouncedHtmlPreview.hooks.js +3 -2
  21. package/dist/features/appearance/constants.d.ts +28 -1
  22. package/dist/features/appearance/constants.js +12 -9
  23. package/dist/features/appearance/react/components/AppearanceTab.js +4 -4
  24. package/dist/features/asset-grid/react/components/AssetGrid.js +8 -3
  25. package/dist/features/asset-grid/react/hooks/useAssetGridKeyboardShortcuts.js +7 -6
  26. package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.js +8 -10
  27. package/dist/features/asset-grid/react/hooks/useRubberBandDrag.js +1 -1
  28. package/dist/features/asset-tree-browser/react/components/AssetTreeFileRow.js +6 -8
  29. package/dist/features/asset-tree-browser/react/hooks/useAssetTreeRowMenu.js +1 -1
  30. package/dist/features/asset-tree-browser/rules.js +1 -3
  31. package/dist/features/browser-chrome/rules.js +10 -8
  32. package/dist/features/charts/browser.js +2 -1
  33. package/dist/features/charts/contract.d.ts +4 -4
  34. package/dist/features/charts/react.js +5 -3
  35. package/dist/features/charts/wire.d.ts +19 -0
  36. package/dist/features/charts/wire.js +20 -2
  37. package/dist/features/connectors/ConnectorsBrowser.js +3 -1
  38. package/dist/features/connectors/hooks/useConnectorAuthorization.js +1 -1
  39. package/dist/features/connectors/hooks/useConnectorCatalog.js +2 -2
  40. package/dist/features/connectors/rules.js +10 -14
  41. package/dist/features/execution/constants.js +0 -1
  42. package/dist/features/execution/react/components/AgentDiagnosticRow.js +2 -0
  43. package/dist/features/execution/react/components/ByokProviderForm.js +1 -3
  44. package/dist/features/execution/react/components/LocalCliAgentSettings.js +2 -1
  45. package/dist/features/execution/react/hooks/use-byok-field-validation.hooks.js +6 -2
  46. package/dist/features/execution/react/hooks/useExecutionTab.js +9 -5
  47. package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +3 -6
  48. package/dist/features/execution/react/hooks/useReasoningControl.js +3 -3
  49. package/dist/features/execution/rules.js +23 -18
  50. package/dist/features/external-mcp/react/components/ExternalMcpTab.js +10 -1
  51. package/dist/features/file-dropzone/rules.js +3 -2
  52. package/dist/features/folder-path-drop/rules.d.ts +2 -3
  53. package/dist/features/folder-path-drop/rules.js +3 -4
  54. package/dist/features/html-editor/canvas-embed-placeholders.js +2 -3
  55. package/dist/features/html-editor/css.js +7 -5
  56. package/dist/features/html-editor/editor-blocks.js +60 -6
  57. package/dist/features/html-editor/protected-elements.js +5 -3
  58. package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +3 -3
  59. package/dist/features/html-editor/source-splice.js +6 -4
  60. package/dist/features/i18n/dictionaries/settings-dialog.ar.js +8 -0
  61. package/dist/features/i18n/dictionaries/settings-dialog.bn.js +8 -0
  62. package/dist/features/i18n/dictionaries/settings-dialog.de.js +8 -0
  63. package/dist/features/i18n/dictionaries/settings-dialog.en.js +8 -0
  64. package/dist/features/i18n/dictionaries/settings-dialog.es.js +8 -0
  65. package/dist/features/i18n/dictionaries/settings-dialog.fa.js +8 -0
  66. package/dist/features/i18n/dictionaries/settings-dialog.fr.js +8 -0
  67. package/dist/features/i18n/dictionaries/settings-dialog.hi.js +8 -0
  68. package/dist/features/i18n/dictionaries/settings-dialog.hu.js +8 -0
  69. package/dist/features/i18n/dictionaries/settings-dialog.id.js +8 -0
  70. package/dist/features/i18n/dictionaries/settings-dialog.it.js +8 -0
  71. package/dist/features/i18n/dictionaries/settings-dialog.ja.js +8 -0
  72. package/dist/features/i18n/dictionaries/settings-dialog.ko.js +8 -0
  73. package/dist/features/i18n/dictionaries/settings-dialog.pl.js +8 -0
  74. package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +8 -0
  75. package/dist/features/i18n/dictionaries/settings-dialog.ru.js +8 -0
  76. package/dist/features/i18n/dictionaries/settings-dialog.th.js +8 -0
  77. package/dist/features/i18n/dictionaries/settings-dialog.tr.js +8 -0
  78. package/dist/features/i18n/dictionaries/settings-dialog.uk.js +8 -0
  79. package/dist/features/i18n/dictionaries/settings-dialog.ur.js +8 -0
  80. package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +8 -0
  81. package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +8 -0
  82. package/dist/features/iframe-pool/react/components/IframeKeepAliveProvider.js +5 -5
  83. package/dist/features/iframe-pool/react/dom-sync.js +2 -2
  84. package/dist/features/integrations/react/components/IntegrationsTab.js +3 -1
  85. package/dist/features/integrations/rules.js +6 -4
  86. package/dist/features/interactive-ui/providers/shadcn/data-table.js +10 -5
  87. package/dist/features/interactive-ui/table-data.js +1 -1
  88. package/dist/features/lexical-rich-text-editor/deserialize.js +2 -2
  89. package/dist/features/lexical-rich-text-editor/mention-parser.js +4 -4
  90. package/dist/features/lexical-rich-text-editor/react/components/RichTextInput.js +2 -1
  91. package/dist/features/lexical-rich-text-editor/react/hooks/useCaretFloatingLayerPosition.js +1 -1
  92. package/dist/features/lexical-rich-text-editor/react/hooks/useMentionColorStamping.js +1 -1
  93. package/dist/features/lexical-rich-text-editor/serialize.js +13 -10
  94. package/dist/features/list-detail-panel/react/components/ListDetailPanel.js +1 -1
  95. package/dist/features/mcp-ui/confirmation-store.js +3 -6
  96. package/dist/features/mcp-ui/surfaces/checkbox.d.ts +2 -0
  97. package/dist/features/mcp-ui/surfaces/choice-group.d.ts +2 -0
  98. package/dist/features/mcp-ui/surfaces/choice-group.js +2 -2
  99. package/dist/features/mcp-ui/surfaces/confirmation.d.ts +5 -0
  100. package/dist/features/mcp-ui/surfaces/confirmation.js +1 -0
  101. package/dist/features/mcp-ui/surfaces/document.d.ts +14 -16
  102. package/dist/features/mcp-ui/surfaces/document.js +46 -7
  103. package/dist/features/mcp-ui/surfaces/fields.d.ts +7 -1
  104. package/dist/features/mcp-ui/surfaces/fields.js +14 -11
  105. package/dist/features/mcp-ui/surfaces/form.js +6 -1
  106. package/dist/features/mcp-ui/surfaces/host-theme.js +2 -1
  107. package/dist/features/mcp-ui/surfaces/index.d.ts +1 -0
  108. package/dist/features/mcp-ui/surfaces/index.js +1 -0
  109. package/dist/features/mcp-ui/surfaces/outcome.js +1 -1
  110. package/dist/features/mcp-ui/surfaces/select.d.ts +2 -0
  111. package/dist/features/mcp-ui/surfaces/select.js +2 -1
  112. package/dist/features/mcp-ui/surfaces/structured-details.d.ts +40 -0
  113. package/dist/features/mcp-ui/surfaces/structured-details.js +159 -0
  114. package/dist/features/mcp-ui/surfaces/text-input.d.ts +2 -0
  115. package/dist/features/mcp-ui/surfaces/text-input.js +1 -1
  116. package/dist/features/mcp-ui/surfaces/tool-approval.d.ts +21 -0
  117. package/dist/features/mcp-ui/surfaces/tool-approval.js +42 -0
  118. package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +2 -1
  119. package/dist/features/memory/async-commit-guard.js +4 -1
  120. package/dist/features/memory/formatters.js +5 -1
  121. package/dist/features/memory/react/components/MemoryConnectedPanel.js +3 -1
  122. package/dist/features/memory/react/components/MemoryEntryCard.js +1 -1
  123. package/dist/features/memory/react/components/MemorySettingsPanel.js +3 -1
  124. package/dist/features/memory/react/hooks/useMemoryConfig.hooks.js +12 -10
  125. package/dist/features/memory/react/hooks/useMemoryConnectors.hooks.js +2 -5
  126. package/dist/features/memory/react/hooks/useMemoryConnectors.rules.js +10 -9
  127. package/dist/features/memory/react/hooks/useMemoryEntries.hooks.js +4 -2
  128. package/dist/features/memory/react/hooks/useMemoryFlash.hooks.js +1 -1
  129. package/dist/features/memory/rules.js +2 -1
  130. package/dist/features/panel-kit/fetch-query/adapter.react.js +3 -2
  131. package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +3 -2
  132. package/dist/features/panel-kit/fetch-query/binding.react.js +2 -1
  133. package/dist/features/panel-kit/helpers/standing-draft-recovery-message.js +13 -4
  134. package/dist/features/panel-kit/hooks/use-dirty-guard.hooks.js +1 -1
  135. package/dist/features/panel-kit/hooks/use-focus-trap.hooks.js +1 -1
  136. package/dist/features/panel-kit/hooks/use-settings-slice.hooks.js +14 -10
  137. package/dist/features/panel-kit/hooks/use-standing-draft-autosave.hooks.js +2 -2
  138. package/dist/features/progress-card/components/ProgressCard.d.ts +1 -1
  139. package/dist/features/progress-card/reference-adapters.js +23 -13
  140. package/dist/features/progress-card/rules.d.ts +0 -1
  141. package/dist/features/progress-card/rules.js +14 -20
  142. package/dist/features/progress-card/types.d.ts +1 -1
  143. package/dist/features/project-locations/dependencies.js +6 -1
  144. package/dist/features/project-locations/react/components/ProjectLocationsTab.js +2 -1
  145. package/dist/features/project-locations/rules.js +2 -1
  146. package/dist/features/resource-dashboard/react/components/ResourceBoardToolbar.js +8 -1
  147. package/dist/features/resource-dashboard/react/components/ResourceCardParts.js +2 -1
  148. package/dist/features/resource-dashboard/react/components/ResourceRowListItem.js +3 -1
  149. package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.js +2 -1
  150. package/dist/features/resource-dashboard/react/components/ResourceRowListView.js +1 -1
  151. package/dist/features/resource-dashboard/react/hooks/useResourceBoard.js +1 -1
  152. package/dist/features/schedule-picker/rules.js +13 -7
  153. package/dist/features/sketch-editor/constants.d.ts +0 -6
  154. package/dist/features/sketch-editor/constants.js +17 -15
  155. package/dist/features/sketch-editor/dom.js +4 -7
  156. package/dist/features/sketch-editor/react/components/SketchMainMenu.js +2 -1
  157. package/dist/features/sketch-editor/react/components/SketchSaveStateBadge.js +2 -1
  158. package/dist/features/sketch-editor/react/hooks/useSketchDomEnhancements.js +1 -1
  159. package/dist/features/sketch-editor/rules.js +13 -12
  160. package/dist/features/skills/dependencies.js +9 -4
  161. package/dist/features/skills/react/components/SkillRow.js +2 -1
  162. package/dist/features/skills/react/components/SkillsTab.js +2 -1
  163. package/dist/features/skills/rules.js +3 -3
  164. package/dist/features/source-config-list/agent-handles.js +4 -3
  165. package/dist/features/source-config-list/react/components/SourceConfigItemCard.js +3 -1
  166. package/dist/features/tab-strip/react/components/TabBar.hooks.js +4 -2
  167. package/dist/features/version-manager/react/components/VersionPreviewFrame.js +4 -1
  168. package/dist/features/version-manager/react/components/VersionSidebar.js +8 -6
  169. package/dist/features/version-manager/react/hooks/usePreviewCanvasSize.js +1 -1
  170. package/dist/features/version-manager/react/hooks/useVersionManager.js +5 -7
  171. package/dist/features/version-manager/rules.js +3 -5
  172. package/dist/features/viewer-shell/react/components/CommentSidePanel.js +2 -1
  173. package/dist/features/viewer-shell/react/components/SegmentedToggle.js +2 -1
  174. package/dist/features/viewer-shell/react/components/ViewerShell.js +2 -1
  175. package/dist/features/viewer-shell/rules.js +8 -7
  176. package/dist/react/components/AgentIcon.js +0 -1
  177. package/dist/react/components/BrandLogo.js +10 -2
  178. package/dist/react/components/CustomSelect.js +1 -1
  179. package/dist/react/components/EditorIcon.js +17 -14
  180. package/dist/react/components/Loading.js +2 -1
  181. package/dist/react/components/OnboardingChipField.js +5 -1
  182. package/dist/react/components/OnboardingDropdown.js +6 -4
  183. package/dist/react/components/PaletteTweaks.js +7 -6
  184. package/dist/react/components/PillButton.js +2 -1
  185. package/dist/react/components/PopoverMenu.js +2 -1
  186. package/dist/react/components/RemixIcon.js +2 -1
  187. package/dist/react/components/SecretInput.hooks.d.ts +2 -25
  188. package/dist/react/components/SecretInput.hooks.js +2 -24
  189. package/dist/react/components/SecretInput.js +5 -4
  190. package/dist/react/components/Toast.js +4 -2
  191. package/dist/react/components/TooltipLayer.js +4 -1
  192. package/dist/react/components/WorkingDirPicker.js +5 -4
  193. package/dist/react/components/agent-icon-data-uris.generated.js +0 -1
  194. package/dist/react/components/remixicon-font-recovery.js +9 -1
  195. package/dist/react/components/select-popover.js +2 -2
  196. package/dist/react/hooks/useBrandFonts.js +1 -1
  197. package/dist/react/hooks/useEdgeAutoScroll.js +1 -1
  198. package/dist/react/hooks/useInView.js +9 -9
  199. package/dist/react/hooks/useResizableSplitPane.js +12 -20
  200. package/dist/react/mcp-ui/useHostSurfaceTokens.js +1 -1
  201. package/dist/renderers/annotation-canvas/react/components/AnnotationCanvas.js +7 -1
  202. package/dist/renderers/annotation-canvas/react/hooks/useAnnotationCanvas.controller.js +4 -2
  203. package/dist/renderers/annotation-canvas/react/hooks/useAnnotationCanvas.js +9 -5
  204. package/dist/renderers/annotation-canvas/rules.js +9 -13
  205. package/dist/renderers/annotation-canvas/theme.js +5 -2
  206. package/dist/renderers/renderers/index.js +1 -1
  207. package/dist/renderers/renderers/markdown.js +4 -6
  208. package/dist/renderers/shiki.js +7 -1
  209. package/dist/theme/apply.js +7 -3
  210. package/dist/utils/class-names.d.ts +3 -0
  211. package/dist/utils/class-names.js +5 -0
  212. package/dist/utils/design-md.js +3 -3
  213. package/dist/utils/ime-composing.d.ts +1 -1
  214. package/dist/utils/ime-composing.js +1 -2
  215. package/dist/utils/localized-url.js +2 -11
  216. package/dist/utils/markdown-scroll-sync.js +1 -1
  217. package/dist/utils/omit-keys.d.ts +3 -0
  218. package/dist/utils/omit-keys.js +8 -0
  219. package/dist/utils/polygon-selection.js +1 -1
  220. package/dist/utils/sse.js +3 -0
  221. package/dist/utils/trim-chars.d.ts +13 -0
  222. package/dist/utils/trim-chars.js +30 -0
  223. package/dist/utils/unhandled-case.d.ts +10 -0
  224. package/dist/utils/unhandled-case.js +12 -0
  225. package/dist/utils/unit-bezier.js +1 -3
  226. package/dist/utils/zip.js +6 -10
  227. package/package.json +32 -29
@@ -51,14 +51,13 @@ export function folderPathsFromDataTransfer(dataTransfer, port) {
51
51
  return paths;
52
52
  }
53
53
  /**
54
- * The text a folder drop inserts: every path, space-joined, in drop order. The one place the format
55
- * lives — a path that itself contains a space is ambiguous in this format, so any change to quoting
56
- * or separators belongs here and nowhere else.
54
+ * The text a folder drop inserts: every path, space-joined, in drop order. Quote whitespace-containing
55
+ * paths so text consumers can distinguish the path from adjacent prose or secrets.
57
56
  *
58
57
  * @complexity Time/space: O(total path length).
59
58
  */
60
59
  export function formatDroppedFolderPaths(paths) {
61
- return paths.join(' ');
60
+ return paths.map(path => /\s/.test(path) ? `"${path}"` : path).join(' ');
62
61
  }
63
62
  /**
64
63
  * A capture-phase drop handler's whole decision. A drop carrying at least one folder with a
@@ -227,9 +227,8 @@ export function applyCanvasEmbedPlaceholders(body, describe) {
227
227
  if (existingCard && !canRefreshRuntimeCard({ el, card: existingCard }, {}))
228
228
  continue;
229
229
  const descriptor = describe(el);
230
- if (!descriptor)
231
- continue;
232
- updatePlaceholder({ el, doc, descriptor, existingCard }, {});
230
+ if (descriptor)
231
+ updatePlaceholder({ el, doc, descriptor, existingCard }, {});
233
232
  }
234
233
  }
235
234
  function canRefreshRuntimeCard({ el, card }, _options = {}) {
@@ -1,3 +1,4 @@
1
+ import { trimTrailingChars } from '../../utils/trim-chars.js';
1
2
  /**
2
3
  * `editor.getCss()` always returns single-line, semicolon-packed CSS — confirmed directly in
3
4
  * GrapesJS's own bundled source (`CssRule.prototype.toCSS`/`getDeclaration`): there is no
@@ -65,7 +66,7 @@ export function prettifyCss(css) {
65
66
  return false;
66
67
  };
67
68
  const openRule = (_input, _options = {}) => {
68
- out = out.replace(/[ \t]+$/, '');
69
+ out = trimTrailingChars(out, ' \t');
69
70
  out += ' {';
70
71
  depth++;
71
72
  atDeclStart = true;
@@ -77,7 +78,7 @@ export function prettifyCss(css) {
77
78
  };
78
79
  const closeRule = (_input, _options = {}) => {
79
80
  depth = Math.max(0, depth - 1);
80
- out = out.replace(/[ \t]+$/, '');
81
+ out = trimTrailingChars(out, ' \t');
81
82
  // A `}` immediately after `{` (an empty rule) needs no newline before it; otherwise close on
82
83
  // its own indented line.
83
84
  if (!out.endsWith('{'))
@@ -137,10 +138,11 @@ export function prettifyCss(css) {
137
138
  out += ' ';
138
139
  i++;
139
140
  skipWhitespace({}, {});
140
- continue;
141
141
  }
142
- out += ch;
143
- i++;
142
+ else {
143
+ out += ch;
144
+ i++;
145
+ }
144
146
  }
145
147
  return out.trim();
146
148
  }
@@ -34,11 +34,54 @@ const RUNTIME_EFFECTS = new Set([
34
34
  const TEXT_EFFECT_TAGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'li', 'dt', 'dd', 'blockquote', 'figcaption', 'label']);
35
35
  const PHRASING_TAGS = new Set([...INLINE_TAGS, 'abbr', 'br', 'cite', 'code', 'data', 'dfn', 'img', 'kbd', 'q', 'samp', 'time', 'var', 'wbr']);
36
36
  const isPhrasingOnly = (el) => el.children.every(child => PHRASING_TAGS.has(child.tagName) && isPhrasingOnly(child));
37
+ /** Closing quotes for each suffix, honoring the same backslash escapes as effect string literals.
38
+ * A failed quoted token can contain another valid token; suffix lookup preserves that recovery
39
+ * without repeatedly scanning an unterminated string. O(n) time and temporary memory. */
40
+ function effectQuoteEnds({ text, quote }, _options = {}) {
41
+ const ends = new Int32Array(text.length + 2).fill(-1);
42
+ for (let i = text.length - 1; i >= 0; i--) {
43
+ const char = text[i];
44
+ if (char === quote)
45
+ ends[i] = i;
46
+ else if (char === '\\' && /[\r\n\u2028\u2029]/.test(text[i + 1] ?? ''))
47
+ ends[i] = -1;
48
+ else
49
+ ends[i] = ends[i + (char === '\\' ? 2 : 1)];
50
+ }
51
+ return ends;
52
+ }
53
+ /** Remove complete quoted strings and parenthesized arguments before splitting effect names.
54
+ * The first closing parenthesis wins, as in the existing effect grammar. O(n) time and memory. */
55
+ function withoutEffectArguments({ text }, _options = {}) {
56
+ const double = effectQuoteEnds({ text, quote: '"' });
57
+ const single = effectQuoteEnds({ text, quote: "'" });
58
+ const lastClose = text.lastIndexOf(')');
59
+ const parts = [];
60
+ let start = 0;
61
+ let i = 0;
62
+ while (i < text.length) {
63
+ let end = -1;
64
+ if (text[i] === '"')
65
+ end = double[i + 1];
66
+ if (text[i] === "'")
67
+ end = single[i + 1];
68
+ if (text[i] === '(' && i < lastClose)
69
+ end = text.indexOf(')', i + 1);
70
+ if (end >= 0) {
71
+ parts.push(text.slice(start, i));
72
+ i = end;
73
+ start = end + 1;
74
+ }
75
+ i++;
76
+ }
77
+ parts.push(text.slice(start));
78
+ return parts.join('');
79
+ }
37
80
  const isEditableEffect = (el) => {
38
81
  if (el.attributes['data-editor'] === 'block')
39
82
  return false;
40
83
  // Quoted selectors and timing/color functions may contain commas, which are not effect separators.
41
- const effects = (el.attributes['data-kui'] ?? '').replace(/"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\([^)]*\)/g, '')
84
+ const effects = withoutEffectArguments({ text: el.attributes['data-kui'] ?? '' })
42
85
  .split(',').map(segment => segment.trim().split(/\s+/)[0]).filter(Boolean);
43
86
  if (effects.some(effect => RUNTIME_EFFECTS.has(effect)))
44
87
  return false;
@@ -72,10 +115,16 @@ function describeBlock({ el, isLive, hasLiveDescendants }, options = {}) {
72
115
  reason = 'embed';
73
116
  return { reason, host };
74
117
  }
118
+ /** `.first.second` from an element's class attribute (first two classes), or undefined when it has none. */
119
+ function classIdentity(className) {
120
+ if (!className)
121
+ return undefined;
122
+ return `.${className.trim().split(/\s+/).slice(0, 2).join('.')}`;
123
+ }
75
124
  function createEditorBlock({ el, reason, host }, options = {}) {
76
125
  const t = options.translate ?? ((key) => key);
77
126
  const id = el.attributes.id;
78
- const identity = id ? `#${id}` : el.attributes.class ? `.${el.attributes.class.trim().split(/\s+/).slice(0, 2).join('.')}` : el.tagName;
127
+ const identity = id ? `#${id}` : classIdentity(el.attributes.class) ?? el.tagName;
79
128
  return {
80
129
  ...el.outerRange, tagName: el.tagName, ...(id ? { id } : {}), reason, element: el,
81
130
  descriptor: reason === 'embed' && host ? host : {
@@ -155,8 +204,10 @@ export function prepareEditorSource({ html }, options = {}) {
155
204
  instances.sort((a, b) => a.outerStart - b.outerStart);
156
205
  let markerAttribute = 'data-jini-raw-source-0';
157
206
  let namespace = 0;
158
- while (html.toLowerCase().includes(markerAttribute))
159
- markerAttribute = `data-jini-raw-source-${++namespace}`;
207
+ while (html.toLowerCase().includes(markerAttribute)) {
208
+ namespace += 1;
209
+ markerAttribute = `data-jini-raw-source-${namespace}`;
210
+ }
160
211
  const prepared = renderSourceShells({ html, instances, blocks: detected.blocks, markerAttribute }, {});
161
212
  return { ok: true, html: prepared, markerAttribute, instances, canvasCss: css.join('\n') };
162
213
  }
@@ -175,7 +226,8 @@ function renderSourceShells({ html, instances, blocks, markerAttribute }, _optio
175
226
  .map(name => ` ${name}="${escapeAttribute(attrs[name])}"`).join('');
176
227
  const tag = instance.nonvisual ? 'span' : instance.tagName;
177
228
  const voidTag = instance.openingEnd === instance.outerEnd;
178
- const shell = `<${tag} ${markerAttribute}="${i}"${layout}>${voidTag && !instance.nonvisual ? '' : `</${tag}>`}`;
229
+ const closingTag = voidTag && !instance.nonvisual ? '' : `</${tag}>`;
230
+ const shell = `<${tag} ${markerAttribute}="${i}"${layout}>${closingTag}`;
179
231
  prepared = prepared.slice(0, instance.outerStart) + shell + prepared.slice(instance.outerEnd);
180
232
  }
181
233
  return prepared;
@@ -186,7 +238,9 @@ export function findEditorBlockOpening({ html, target }, _options = {}) {
186
238
  let result;
187
239
  const walk = (el) => {
188
240
  if (el.tagName === target.tagName.toLowerCase() && (target.id === undefined || el.attributes.id === target.id)) {
189
- if (occurrence++ === target.occurrenceIndex && el.outerRange) {
241
+ const index = occurrence;
242
+ occurrence += 1;
243
+ if (index === target.occurrenceIndex && el.outerRange) {
190
244
  const { outerStart: start, openingEnd: end } = el.outerRange;
191
245
  result = { start, end, openingTag: html.slice(start, end) };
192
246
  }
@@ -77,10 +77,12 @@ function selectedSourceStart({ wrapper, selected, original, html }, _options = {
77
77
  let copiesBefore = 0;
78
78
  let reached = false;
79
79
  visit(wrapper, component => {
80
- if (component === selected)
80
+ if (component === selected) {
81
81
  reached = true;
82
- else if (!reached && component.is(PROTECTED_ELEMENT_TYPE) && protectedElementHtml({ component }, {}) === original)
83
- copiesBefore++;
82
+ return;
83
+ }
84
+ if (!reached && component.is(PROTECTED_ELEMENT_TYPE) && protectedElementHtml({ component }, {}) === original)
85
+ copiesBefore += 1;
84
86
  });
85
87
  let start = -1;
86
88
  for (let i = 0; i <= copiesBefore; i++)
@@ -227,7 +227,7 @@ export function useInteractiveHtmlEditor(html, onChange, isProtectedElement, can
227
227
  useEffect(() => {
228
228
  const wrapper = wrapperRef.current;
229
229
  if (!wrapper)
230
- return;
230
+ return undefined;
231
231
  const sourcePlan = prepareEditorSource({ html }, { isProtectedElement, describeHostElement: describeEmbedPlaceholder, translate: options.translate });
232
232
  let integrityFailure;
233
233
  const reportSourceError = (error) => {
@@ -237,7 +237,7 @@ export function useInteractiveHtmlEditor(html, onChange, isProtectedElement, can
237
237
  };
238
238
  if (!sourcePlan.ok) {
239
239
  reportSourceError(new EditorSourceError({ message: sourcePlan.problem }, {}));
240
- return;
240
+ return undefined;
241
241
  }
242
242
  const mountEl = document.createElement('div');
243
243
  mountEl.style.height = '100%';
@@ -249,7 +249,7 @@ export function useInteractiveHtmlEditor(html, onChange, isProtectedElement, can
249
249
  catch {
250
250
  reportSourceError(new EditorSourceError());
251
251
  mountEl.remove();
252
- return;
252
+ return undefined;
253
253
  }
254
254
  const decorate = () => {
255
255
  protectTextAncestors({ editor }, {});
@@ -34,9 +34,7 @@ function recordInnerRange({ node, currentPath, out }, _options = {}) {
34
34
  function indexChildren(children, parentPath, out) {
35
35
  let elementIndex = 0;
36
36
  for (const node of children) {
37
- if (!isElement(node))
38
- continue;
39
- if (UNINDEXED_TAGS.has(node.tagName))
37
+ if (!isElement(node) || UNINDEXED_TAGS.has(node.tagName))
40
38
  continue;
41
39
  const currentPath = [...parentPath, elementIndex];
42
40
  recordInnerRange({ node, currentPath, out }, {});
@@ -134,7 +132,11 @@ export function indexSourceElements({ html }, _options = {}) {
134
132
  let slot = 0;
135
133
  const elements = nodes.filter(isElement).map(node => {
136
134
  const atom = UNINDEXED_TAGS.has(node.tagName);
137
- const path = atom ? null : [...parentPath, slot++];
135
+ let path = null;
136
+ if (!atom) {
137
+ path = [...parentPath, slot];
138
+ slot += 1;
139
+ }
138
140
  const loc = node.sourceCodeLocation;
139
141
  const children = walk({ nodes: node.childNodes, parentPath: path ?? parentPath, parentStart: loc?.startTag?.endOffset ?? parentStart, parentEnd: loc?.endTag?.startOffset ?? parentEnd }, {});
140
142
  const outerRange = sourceOuterRange({ node, html, parentStart, parentEnd }, {});
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_AR = {
68
68
  'Custom instructions': 'تعليمات مخصصة',
69
69
  'Custom model id': 'معرّف نموذج مخصص',
70
70
  'Custom…': 'مخصص…',
71
+ 'Charcoal': 'فحمي',
72
+ 'Clay': 'طيني',
73
+ 'Violet': 'بنفسجي',
74
+ 'Green': 'أخضر',
75
+ 'Red': 'أحمر',
76
+ 'Amber': 'كهرماني',
77
+ 'Teal': 'أزرق مخضر',
78
+ 'Pink': 'وردي',
71
79
  'Default accent color': 'لون التمييز الافتراضي',
72
80
  'Default endpoint. Usually no need to change this.': 'نقطة النهاية الافتراضية. عادةً لا حاجة لتغيير هذا.',
73
81
  'Default model': 'النموذج الافتراضي',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_BN = {
68
68
  'Custom instructions': 'কাস্টম নির্দেশনা',
69
69
  'Custom model id': 'কাস্টম মডেল আইডি',
70
70
  'Custom…': 'কাস্টম…',
71
+ 'Charcoal': 'কয়লা',
72
+ 'Clay': 'মাটি',
73
+ 'Violet': 'বেগুনি',
74
+ 'Green': 'সবুজ',
75
+ 'Red': 'লাল',
76
+ 'Amber': 'অ্যাম্বার',
77
+ 'Teal': 'নীলচে সবুজ',
78
+ 'Pink': 'গোলাপি',
71
79
  'Default accent color': 'ডিফল্ট হাইলাইট রং',
72
80
  'Default endpoint. Usually no need to change this.': 'ডিফল্ট এন্ডপয়েন্ট। সাধারণত এটি পরিবর্তনের প্রয়োজন হয় না।',
73
81
  'Default model': 'ডিফল্ট মডেল',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_DE = {
68
68
  'Custom instructions': 'Benutzerdefinierte Anweisungen',
69
69
  'Custom model id': 'Benutzerdefinierte Modell-ID',
70
70
  'Custom…': 'Benutzerdefiniert…',
71
+ 'Charcoal': 'Anthrazit',
72
+ 'Clay': 'Ton',
73
+ 'Violet': 'Violett',
74
+ 'Green': 'Grün',
75
+ 'Red': 'Rot',
76
+ 'Amber': 'Bernstein',
77
+ 'Teal': 'Petrol',
78
+ 'Pink': 'Pink',
71
79
  'Default accent color': 'Standard-Akzentfarbe',
72
80
  'Default endpoint. Usually no need to change this.': 'Standard-Endpunkt. Muss normalerweise nicht geändert werden.',
73
81
  'Default model': 'Standardmodell',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_EN = {
68
68
  'Custom instructions': 'Custom instructions',
69
69
  'Custom model id': 'Custom model id',
70
70
  'Custom…': 'Custom…',
71
+ 'Charcoal': 'Charcoal',
72
+ 'Clay': 'Clay',
73
+ 'Violet': 'Violet',
74
+ 'Green': 'Green',
75
+ 'Red': 'Red',
76
+ 'Amber': 'Amber',
77
+ 'Teal': 'Teal',
78
+ 'Pink': 'Pink',
71
79
  'Default accent color': 'Default accent color',
72
80
  'Default endpoint. Usually no need to change this.': 'Default endpoint. Usually no need to change this.',
73
81
  'Default model': 'Default model',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_ES = {
68
68
  'Custom instructions': 'Instrucciones personalizadas',
69
69
  'Custom model id': 'Id. de modelo personalizado',
70
70
  'Custom…': 'Personalizado…',
71
+ 'Charcoal': 'Carbón',
72
+ 'Clay': 'Arcilla',
73
+ 'Violet': 'Violeta',
74
+ 'Green': 'Verde',
75
+ 'Red': 'Rojo',
76
+ 'Amber': 'Ámbar',
77
+ 'Teal': 'Verde azulado',
78
+ 'Pink': 'Rosa',
71
79
  'Default accent color': 'Color de acento predeterminado',
72
80
  'Default endpoint. Usually no need to change this.': 'Endpoint predeterminado. Normalmente no hace falta cambiarlo.',
73
81
  'Default model': 'Modelo predeterminado',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_FA = {
68
68
  'Custom instructions': 'دستورالعمل‌های سفارشی',
69
69
  'Custom model id': 'شناسهٔ مدل سفارشی',
70
70
  'Custom…': 'سفارشی…',
71
+ 'Charcoal': 'زغالی',
72
+ 'Clay': 'سفالی',
73
+ 'Violet': 'بنفش',
74
+ 'Green': 'سبز',
75
+ 'Red': 'قرمز',
76
+ 'Amber': 'کهربایی',
77
+ 'Teal': 'سبزآبی',
78
+ 'Pink': 'صورتی',
71
79
  'Default accent color': 'رنگ تأکیدی پیش‌فرض',
72
80
  'Default endpoint. Usually no need to change this.': 'نقطهٔ پایانی پیش‌فرض. معمولاً نیازی به تغییر آن نیست.',
73
81
  'Default model': 'مدل پیش‌فرض',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_FR = {
68
68
  'Custom instructions': 'Instructions personnalisées',
69
69
  'Custom model id': 'Identifiant de modèle personnalisé',
70
70
  'Custom…': 'Personnalisé…',
71
+ 'Charcoal': 'Anthracite',
72
+ 'Clay': 'Argile',
73
+ 'Violet': 'Violet',
74
+ 'Green': 'Vert',
75
+ 'Red': 'Rouge',
76
+ 'Amber': 'Ambre',
77
+ 'Teal': 'Bleu canard',
78
+ 'Pink': 'Rose',
71
79
  'Default accent color': 'Couleur d\'accent par défaut',
72
80
  'Default endpoint. Usually no need to change this.': 'Point de terminaison par défaut. Il n\'est généralement pas nécessaire de le modifier.',
73
81
  'Default model': 'Modèle par défaut',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_HI = {
68
68
  'Custom instructions': 'कस्टम निर्देश',
69
69
  'Custom model id': 'कस्टम मॉडल आईडी',
70
70
  'Custom…': 'कस्टम…',
71
+ 'Charcoal': 'चारकोल',
72
+ 'Clay': 'मिट्टी',
73
+ 'Violet': 'बैंगनी',
74
+ 'Green': 'हरा',
75
+ 'Red': 'लाल',
76
+ 'Amber': 'एम्बर',
77
+ 'Teal': 'हरित-नील',
78
+ 'Pink': 'गुलाबी',
71
79
  'Default accent color': 'डिफ़ॉल्ट हाइलाइट रंग',
72
80
  'Default endpoint. Usually no need to change this.': 'डिफ़ॉल्ट एंडपॉइंट। आमतौर पर इसे बदलने की आवश्यकता नहीं होती।',
73
81
  'Default model': 'डिफ़ॉल्ट मॉडल',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_HU = {
68
68
  'Custom instructions': 'Egyéni utasítások',
69
69
  'Custom model id': 'Egyéni modellazonosító',
70
70
  'Custom…': 'Egyéni…',
71
+ 'Charcoal': 'Grafit',
72
+ 'Clay': 'Agyag',
73
+ 'Violet': 'Ibolya',
74
+ 'Green': 'Zöld',
75
+ 'Red': 'Piros',
76
+ 'Amber': 'Borostyán',
77
+ 'Teal': 'Kékeszöld',
78
+ 'Pink': 'Rózsaszín',
71
79
  'Default accent color': 'Alapértelmezett kiemelőszín',
72
80
  'Default endpoint. Usually no need to change this.': 'Alapértelmezett végpont. Általában nem szükséges módosítani.',
73
81
  'Default model': 'Alapértelmezett modell',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_ID = {
68
68
  'Custom instructions': 'Instruksi kustom',
69
69
  'Custom model id': 'ID model kustom',
70
70
  'Custom…': 'Kustom…',
71
+ 'Charcoal': 'Arang',
72
+ 'Clay': 'Tanah liat',
73
+ 'Violet': 'Ungu',
74
+ 'Green': 'Hijau',
75
+ 'Red': 'Merah',
76
+ 'Amber': 'Kuning amber',
77
+ 'Teal': 'Hijau kebiruan',
78
+ 'Pink': 'Merah muda',
71
79
  'Default accent color': 'Warna aksen default',
72
80
  'Default endpoint. Usually no need to change this.': 'Endpoint default. Biasanya tidak perlu diubah.',
73
81
  'Default model': 'Model default',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_IT = {
68
68
  'Custom instructions': 'Istruzioni personalizzate',
69
69
  'Custom model id': 'ID modello personalizzato',
70
70
  'Custom…': 'Personalizzato…',
71
+ 'Charcoal': 'Antracite',
72
+ 'Clay': 'Argilla',
73
+ 'Violet': 'Viola',
74
+ 'Green': 'Verde',
75
+ 'Red': 'Rosso',
76
+ 'Amber': 'Ambra',
77
+ 'Teal': 'Verde acqua',
78
+ 'Pink': 'Rosa',
71
79
  'Default accent color': 'Colore di accento predefinito',
72
80
  'Default endpoint. Usually no need to change this.': 'Endpoint predefinito. Di solito non è necessario modificarlo.',
73
81
  'Default model': 'Modello predefinito',
@@ -69,6 +69,14 @@ export const SETTINGS_DIALOG_JA = {
69
69
  'Custom instructions': 'カスタム指示',
70
70
  'Custom model id': 'カスタムモデルID',
71
71
  'Custom…': 'カスタム…',
72
+ 'Charcoal': 'チャコール',
73
+ 'Clay': 'クレイ',
74
+ 'Violet': 'バイオレット',
75
+ 'Green': 'グリーン',
76
+ 'Red': 'レッド',
77
+ 'Amber': 'アンバー',
78
+ 'Teal': 'ティール',
79
+ 'Pink': 'ピンク',
72
80
  'Default accent color': '既定のアクセントカラー',
73
81
  'Default endpoint. Usually no need to change this.': '既定のエンドポイントです。通常は変更する必要はありません。',
74
82
  'Default model': '既定のモデル',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_KO = {
68
68
  'Custom instructions': '사용자 지정 지침',
69
69
  'Custom model id': '사용자 지정 모델 ID',
70
70
  'Custom…': '사용자 지정…',
71
+ 'Charcoal': '차콜',
72
+ 'Clay': '클레이',
73
+ 'Violet': '바이올렛',
74
+ 'Green': '초록',
75
+ 'Red': '빨강',
76
+ 'Amber': '호박색',
77
+ 'Teal': '청록',
78
+ 'Pink': '분홍',
71
79
  'Default accent color': '기본 강조 색상',
72
80
  'Default endpoint. Usually no need to change this.': '기본 엔드포인트입니다. 보통 변경할 필요가 없습니다.',
73
81
  'Default model': '기본 모델',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_PL = {
68
68
  'Custom instructions': 'Niestandardowe instrukcje',
69
69
  'Custom model id': 'Niestandardowy identyfikator modelu',
70
70
  'Custom…': 'Niestandardowy…',
71
+ 'Charcoal': 'Grafitowy',
72
+ 'Clay': 'Gliniany',
73
+ 'Violet': 'Fioletowy',
74
+ 'Green': 'Zielony',
75
+ 'Red': 'Czerwony',
76
+ 'Amber': 'Bursztynowy',
77
+ 'Teal': 'Morski',
78
+ 'Pink': 'Różowy',
71
79
  'Default accent color': 'Domyślny kolor akcentu',
72
80
  'Default endpoint. Usually no need to change this.': 'Domyślny punkt końcowy. Zwykle nie trzeba go zmieniać.',
73
81
  'Default model': 'Model domyślny',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_PT_BR = {
68
68
  'Custom instructions': 'Instruções personalizadas',
69
69
  'Custom model id': 'ID de modelo personalizado',
70
70
  'Custom…': 'Personalizado…',
71
+ 'Charcoal': 'Carvão',
72
+ 'Clay': 'Argila',
73
+ 'Violet': 'Violeta',
74
+ 'Green': 'Verde',
75
+ 'Red': 'Vermelho',
76
+ 'Amber': 'Âmbar',
77
+ 'Teal': 'Azul-petróleo',
78
+ 'Pink': 'Rosa',
71
79
  'Default accent color': 'Cor de destaque padrão',
72
80
  'Default endpoint. Usually no need to change this.': 'Endpoint padrão. Geralmente não é necessário alterar isso.',
73
81
  'Default model': 'Modelo padrão',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_RU = {
68
68
  'Custom instructions': 'Пользовательские инструкции',
69
69
  'Custom model id': 'Пользовательский id. модели',
70
70
  'Custom…': 'Другое…',
71
+ 'Charcoal': 'Угольный',
72
+ 'Clay': 'Глиняный',
73
+ 'Violet': 'Фиолетовый',
74
+ 'Green': 'Зелёный',
75
+ 'Red': 'Красный',
76
+ 'Amber': 'Янтарный',
77
+ 'Teal': 'Бирюзовый',
78
+ 'Pink': 'Розовый',
71
79
  'Default accent color': 'Акцентный цвет по умолчанию',
72
80
  'Default endpoint. Usually no need to change this.': 'Конечная точка по умолчанию. Обычно менять её не требуется.',
73
81
  'Default model': 'Модель по умолчанию',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_TH = {
68
68
  'Custom instructions': 'คำสั่งที่กำหนดเอง',
69
69
  'Custom model id': 'รหัสโมเดลที่กำหนดเอง',
70
70
  'Custom…': 'กำหนดเอง…',
71
+ 'Charcoal': 'ถ่าน',
72
+ 'Clay': 'ดินเผา',
73
+ 'Violet': 'ม่วง',
74
+ 'Green': 'เขียว',
75
+ 'Red': 'แดง',
76
+ 'Amber': 'อำพัน',
77
+ 'Teal': 'เขียวน้ำทะเล',
78
+ 'Pink': 'ชมพู',
71
79
  'Default accent color': 'สีเน้นเริ่มต้น',
72
80
  'Default endpoint. Usually no need to change this.': 'เอนด์พอยต์เริ่มต้น โดยปกติไม่จำเป็นต้องเปลี่ยนค่านี้',
73
81
  'Default model': 'โมเดลเริ่มต้น',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_TR = {
68
68
  'Custom instructions': 'Özel talimatlar',
69
69
  'Custom model id': 'Özel model kimliği',
70
70
  'Custom…': 'Özel…',
71
+ 'Charcoal': 'Kömür',
72
+ 'Clay': 'Kil',
73
+ 'Violet': 'Mor',
74
+ 'Green': 'Yeşil',
75
+ 'Red': 'Kırmızı',
76
+ 'Amber': 'Kehribar',
77
+ 'Teal': 'Camgöbeği',
78
+ 'Pink': 'Pembe',
71
79
  'Default accent color': 'Varsayılan vurgu rengi',
72
80
  'Default endpoint. Usually no need to change this.': 'Varsayılan uç nokta. Genellikle bunu değiştirmeye gerek yoktur.',
73
81
  'Default model': 'Varsayılan model',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_UK = {
68
68
  'Custom instructions': 'Власні інструкції',
69
69
  'Custom model id': 'Власний ідентифікатор моделі',
70
70
  'Custom…': 'Власний…',
71
+ 'Charcoal': 'Вугільний',
72
+ 'Clay': 'Глиняний',
73
+ 'Violet': 'Фіолетовий',
74
+ 'Green': 'Зелений',
75
+ 'Red': 'Червоний',
76
+ 'Amber': 'Бурштиновий',
77
+ 'Teal': 'Бірюзовий',
78
+ 'Pink': 'Рожевий',
71
79
  'Default accent color': 'Акцентний колір за замовчуванням',
72
80
  'Default endpoint. Usually no need to change this.': 'Кінцева точка за замовчуванням. Зазвичай змінювати її не потрібно.',
73
81
  'Default model': 'Модель за замовчуванням',
@@ -68,6 +68,14 @@ export const SETTINGS_DIALOG_UR = {
68
68
  'Custom instructions': 'کسٹم ہدایات',
69
69
  'Custom model id': 'کسٹم ماڈل آئی ڈی',
70
70
  'Custom…': 'کسٹم…',
71
+ 'Charcoal': 'کوئلہ',
72
+ 'Clay': 'مٹی',
73
+ 'Violet': 'بنفشی',
74
+ 'Green': 'سبز',
75
+ 'Red': 'سرخ',
76
+ 'Amber': 'کہربائی',
77
+ 'Teal': 'نیلگوں سبز',
78
+ 'Pink': 'گلابی',
71
79
  'Default accent color': 'ڈیفالٹ نمایاں رنگ',
72
80
  'Default endpoint. Usually no need to change this.': 'ڈیفالٹ اینڈ پوائنٹ۔ عام طور پر اسے تبدیل کرنے کی ضرورت نہیں ہوتی۔',
73
81
  'Default model': 'ڈیفالٹ ماڈل',
@@ -69,6 +69,14 @@ export const SETTINGS_DIALOG_ZH_CN = {
69
69
  'Custom instructions': '自定义指令',
70
70
  'Custom model id': '自定义模型 ID',
71
71
  'Custom…': '自定义…',
72
+ 'Charcoal': '炭灰',
73
+ 'Clay': '陶土',
74
+ 'Violet': '紫罗兰',
75
+ 'Green': '绿色',
76
+ 'Red': '红色',
77
+ 'Amber': '琥珀色',
78
+ 'Teal': '青色',
79
+ 'Pink': '粉色',
72
80
  'Default accent color': '默认强调色',
73
81
  'Default endpoint. Usually no need to change this.': '默认终结点,通常无需更改。',
74
82
  'Default model': '默认模型',
@@ -69,6 +69,14 @@ export const SETTINGS_DIALOG_ZH_TW = {
69
69
  'Custom instructions': '自訂指令',
70
70
  'Custom model id': '自訂模型 ID',
71
71
  'Custom…': '自訂…',
72
+ 'Charcoal': '炭灰',
73
+ 'Clay': '陶土',
74
+ 'Violet': '紫羅蘭',
75
+ 'Green': '綠色',
76
+ 'Red': '紅色',
77
+ 'Amber': '琥珀色',
78
+ 'Teal': '青色',
79
+ 'Pink': '粉紅色',
72
80
  'Default accent color': '預設強調色',
73
81
  'Default endpoint. Usually no need to change this.': '預設端點,通常不需要變更。',
74
82
  'Default model': '預設模型',
@@ -35,15 +35,15 @@ export function IframeKeepAliveProvider({ children, maxMounted = DEFAULT_MAX_MOU
35
35
  const pool = useMemo(() => ({
36
36
  attach(key, host, create) {
37
37
  let entry = entriesRef.current.get(key);
38
- if (!entry) {
39
- entry = { key, element: create(), lastUsedAt: Date.now() };
40
- entriesRef.current.set(key, entry);
41
- }
42
- else if (!activeKeysRef.current.has(key)) {
38
+ if (entry && !activeKeysRef.current.has(key)) {
43
39
  // Reattaching a parked entry — undo the hidden/inert markers
44
40
  // `release()` set, or the reused iframe would stay invisible.
45
41
  unparkIframeElement(entry.element);
46
42
  }
43
+ if (!entry) {
44
+ entry = { key, element: create(), lastUsedAt: Date.now() };
45
+ entriesRef.current.set(key, entry);
46
+ }
47
47
  entry.lastUsedAt = Date.now();
48
48
  activeKeysRef.current.add(key);
49
49
  host.appendChild(entry.element);
@@ -1,10 +1,10 @@
1
1
  export function setForwardedRef(ref, value) {
2
2
  if (typeof ref === 'function') {
3
3
  ref(value);
4
+ return;
4
5
  }
5
- else if (ref) {
6
+ if (ref)
6
7
  ref.current = value;
7
- }
8
8
  }
9
9
  export function propNameToAttributeName(name) {
10
10
  if (name === 'className')