@syntrologie/adapt-nav 2.20.0 β†’ 2.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/editor.js CHANGED
@@ -3332,6 +3332,236 @@ function itemCardHeader(opts) {
3332
3332
  `;
3333
3333
  }
3334
3334
 
3335
+ // ../../shared-editor-ui/dist/components/TileChromeEditorLit.js
3336
+ import { css, html as html2, LitElement, nothing as nothing2 } from "lit";
3337
+ var EMOJI_LIST = [
3338
+ "\u{1F4B5}",
3339
+ "\u{1F4B0}",
3340
+ "\u{1F3DB}\uFE0F",
3341
+ "\u23ED\uFE0F",
3342
+ "\u27A1\uFE0F",
3343
+ "\u{1F4A1}",
3344
+ "\u{1F4CB}",
3345
+ "\u2705",
3346
+ "\u26A0\uFE0F",
3347
+ "\u{1F6E1}\uFE0F",
3348
+ "\u{1F4C8}",
3349
+ "\u{1F52C}",
3350
+ "\u{1F48A}",
3351
+ "\u{1F4C4}",
3352
+ "\u{1F9EA}",
3353
+ "\u{1F501}",
3354
+ "\u{1F9E0}",
3355
+ "\u{1F319}",
3356
+ "\u{1F4E6}",
3357
+ "\u{1F69A}",
3358
+ "\u{1F331}",
3359
+ "\u26A1",
3360
+ "\u{1F525}",
3361
+ "\u{1F333}",
3362
+ "\u{1F33F}",
3363
+ "\u2753",
3364
+ "\u{1F9ED}",
3365
+ "\u{1F4DD}",
3366
+ "\u{1F3AF}",
3367
+ "\u{1F3C6}",
3368
+ "\u2728",
3369
+ "\u{1F4AC}",
3370
+ "\u{1F3AE}",
3371
+ "\u23F1\uFE0F",
3372
+ "\u{1F4D6}",
3373
+ "\u{1F514}",
3374
+ "\u{1F393}",
3375
+ "\u23F0",
3376
+ "\u{1F504}",
3377
+ "\u{1F464}",
3378
+ "\u{1F3E0}",
3379
+ "\u{1F6D2}",
3380
+ "\u{1F4CA}",
3381
+ "\u{1F4C9}",
3382
+ "\u{1F967}",
3383
+ "\u{1F4B9}",
3384
+ "\u{1F321}\uFE0F"
3385
+ ];
3386
+ var TileChromeEditorLit = class extends LitElement {
3387
+ constructor() {
3388
+ super(...arguments);
3389
+ this.tileMeta = { title: "", subtitle: "", icon: "" };
3390
+ this.onChange = () => {
3391
+ };
3392
+ this._pickerOpen = false;
3393
+ }
3394
+ _patch(field, value) {
3395
+ const updated = { ...this.tileMeta, [field]: value };
3396
+ this.tileMeta = updated;
3397
+ this.onChange(updated);
3398
+ }
3399
+ _selectEmoji(emoji) {
3400
+ const value = this.tileMeta.icon === emoji ? "" : emoji;
3401
+ this._patch("icon", value);
3402
+ }
3403
+ render() {
3404
+ return html2`
3405
+ <form @submit=${(e) => e.preventDefault()}>
3406
+ <label>
3407
+ <span>Title</span>
3408
+ <input
3409
+ name="title"
3410
+ type="text"
3411
+ .value=${this.tileMeta.title}
3412
+ @input=${(e) => this._patch("title", e.target.value)}
3413
+ />
3414
+ </label>
3415
+
3416
+ <label>
3417
+ <span>Subtitle</span>
3418
+ <input
3419
+ name="subtitle"
3420
+ type="text"
3421
+ .value=${this.tileMeta.subtitle}
3422
+ placeholder="Optional"
3423
+ @input=${(e) => this._patch("subtitle", e.target.value)}
3424
+ />
3425
+ </label>
3426
+
3427
+ <div class="icon-section">
3428
+ <span>Icon</span>
3429
+ <button
3430
+ type="button"
3431
+ class="icon-toggle"
3432
+ data-emoji-toggle
3433
+ @click=${() => {
3434
+ this._pickerOpen = !this._pickerOpen;
3435
+ }}
3436
+ >
3437
+ ${this.tileMeta.icon ? html2`<span style="font-size: 20px">${this.tileMeta.icon}</span>` : html2`<span style="color: var(--syntro-text-tertiary, #87919f)">Choose icon…</span>`}
3438
+ </button>
3439
+
3440
+ ${this._pickerOpen ? html2`
3441
+ <div data-emoji-grid class="emoji-grid">
3442
+ ${EMOJI_LIST.map((emoji) => html2`
3443
+ <button
3444
+ type="button"
3445
+ data-emoji=${emoji}
3446
+ class=${this.tileMeta.icon === emoji ? "selected" : ""}
3447
+ @click=${() => this._selectEmoji(emoji)}
3448
+ title=${emoji}
3449
+ >${emoji}</button>
3450
+ `)}
3451
+ </div>
3452
+ ` : nothing2}
3453
+ </div>
3454
+ </form>
3455
+ `;
3456
+ }
3457
+ };
3458
+ TileChromeEditorLit.styles = css`
3459
+ :host {
3460
+ display: block;
3461
+ width: 100%;
3462
+ font-family: system-ui, -apple-system, sans-serif;
3463
+ }
3464
+ form {
3465
+ display: flex;
3466
+ flex-direction: column;
3467
+ gap: 16px;
3468
+ }
3469
+ label {
3470
+ display: flex;
3471
+ flex-direction: column;
3472
+ gap: 6px;
3473
+ }
3474
+ label > span {
3475
+ font-size: 13px;
3476
+ font-weight: 500;
3477
+ color: var(--syntro-text-secondary, #a8afba);
3478
+ }
3479
+ input[type='text'] {
3480
+ width: 100%;
3481
+ box-sizing: border-box;
3482
+ padding: 8px 12px;
3483
+ border-radius: 6px;
3484
+ border: 1px solid var(--syntro-input-field-border-default, #2b333f);
3485
+ background: var(--syntro-input-field-bg-default, #0e1114);
3486
+ color: var(--syntro-text-primary, #cbd0d7);
3487
+ font-size: 14px;
3488
+ font-family: inherit;
3489
+ outline: none;
3490
+ }
3491
+ input[type='text']:focus {
3492
+ border-color: var(--syntro-input-field-border-selected, #b72e2a);
3493
+ box-shadow: var(--syntro-focus-ring-primary, 0 0 0 4px rgba(221, 109, 105, 0.25));
3494
+ }
3495
+ .icon-section {
3496
+ display: flex;
3497
+ flex-direction: column;
3498
+ gap: 6px;
3499
+ }
3500
+ .icon-section > span {
3501
+ font-size: 13px;
3502
+ font-weight: 500;
3503
+ color: var(--syntro-text-secondary, #a8afba);
3504
+ }
3505
+ .icon-toggle {
3506
+ display: inline-flex;
3507
+ align-items: center;
3508
+ gap: 8px;
3509
+ padding: 8px 12px;
3510
+ border-radius: 6px;
3511
+ border: 1px solid var(--syntro-input-field-border-default, #2b333f);
3512
+ background: var(--syntro-input-field-bg-default, #0e1114);
3513
+ color: var(--syntro-text-primary, #cbd0d7);
3514
+ font-size: 14px;
3515
+ cursor: pointer;
3516
+ font-family: inherit;
3517
+ }
3518
+ .icon-toggle:hover {
3519
+ border-color: var(--syntro-input-field-border-selected, #b72e2a);
3520
+ }
3521
+ .emoji-grid {
3522
+ display: grid;
3523
+ grid-template-columns: repeat(8, 1fr);
3524
+ gap: 4px;
3525
+ padding: 8px;
3526
+ margin-top: 4px;
3527
+ background: var(--syntro-background-secondary, #07080a);
3528
+ border: 1px solid var(--syntro-input-field-border-default, #2b333f);
3529
+ border-radius: 8px;
3530
+ max-height: 200px;
3531
+ overflow-y: auto;
3532
+ }
3533
+ .emoji-grid button {
3534
+ display: flex;
3535
+ align-items: center;
3536
+ justify-content: center;
3537
+ width: 36px;
3538
+ height: 36px;
3539
+ border: 1px solid transparent;
3540
+ border-radius: 6px;
3541
+ background: transparent;
3542
+ font-size: 18px;
3543
+ cursor: pointer;
3544
+ padding: 0;
3545
+ transition: background 100ms ease, border-color 100ms ease;
3546
+ }
3547
+ .emoji-grid button:hover {
3548
+ background: rgba(183, 46, 42, 0.1);
3549
+ border-color: rgba(183, 46, 42, 0.3);
3550
+ }
3551
+ .emoji-grid button.selected {
3552
+ background: rgba(183, 46, 42, 0.2);
3553
+ border-color: var(--syntro-button-primary-bg-default, #b72e2a);
3554
+ }
3555
+ `;
3556
+ TileChromeEditorLit.properties = {
3557
+ tileMeta: { attribute: false },
3558
+ onChange: { attribute: false },
3559
+ _pickerOpen: { state: true }
3560
+ };
3561
+ if (!customElements.get("syntro-tile-chrome-editor")) {
3562
+ customElements.define("syntro-tile-chrome-editor", TileChromeEditorLit);
3563
+ }
3564
+
3335
3565
  // ../../shared-editor-ui/dist/components/TriggerJourney.js
3336
3566
  var import_jsx_runtime19 = __toESM(require_jsx_runtime(), 1);
3337
3567
 
@@ -3564,7 +3794,7 @@ var INTERACTIVE_TAGS = new Set(action_step_field_mapping_default.interactive_tag
3564
3794
  var INTERACTIVE_ROLES = new Set(action_step_field_mapping_default.interactive_roles);
3565
3795
 
3566
3796
  // src/editor.ts
3567
- import { html as html10, LitElement as LitElement9, nothing as nothing5 } from "lit";
3797
+ import { html as html14, LitElement as LitElement13, nothing as nothing9 } from "lit";
3568
3798
 
3569
3799
  // src/summarize.ts
3570
3800
  var MAX_TITLE_LEN = 30;
@@ -3608,7 +3838,7 @@ function isOwnAction(action) {
3608
3838
  }
3609
3839
 
3610
3840
  // ../../shared-editor-ui/src/components/AnchorPickerLit.ts
3611
- import { html as html2, LitElement, render as litRender, nothing as nothing2 } from "lit";
3841
+ import { html as html3, LitElement as LitElement2, render as litRender, nothing as nothing3 } from "lit";
3612
3842
  import { styleMap } from "lit/directives/style-map.js";
3613
3843
 
3614
3844
  // ../../shared-editor-ui/src/utils/selectorGenerator.ts
@@ -3727,7 +3957,7 @@ function isDynamicClass(className) {
3727
3957
  var HIGHLIGHT_COLOR = colors_default.blue[4];
3728
3958
  var HIGHLIGHT_BG = "rgba(25, 105, 254, 0.1)";
3729
3959
  var DEFAULT_EXCLUDE_SELECTOR = "[data-syntro-editor-panel], [data-shadow-canvas-id], .syntro-tooltip, .syntro-modal, .syntro-highlight, [data-syntro-anchor-picker]";
3730
- var AnchorPickerLit = class extends LitElement {
3960
+ var AnchorPickerLit = class extends LitElement2 {
3731
3961
  constructor() {
3732
3962
  super(...arguments);
3733
3963
  this.isActive = false;
@@ -3853,7 +4083,7 @@ var AnchorPickerLit = class extends LitElement {
3853
4083
  }
3854
4084
  _destroyPortal() {
3855
4085
  if (this._portalDiv) {
3856
- litRender(nothing2, this._portalDiv);
4086
+ litRender(nothing3, this._portalDiv);
3857
4087
  this._portalDiv.remove();
3858
4088
  this._portalDiv = null;
3859
4089
  this._overlayEl = null;
@@ -3889,13 +4119,13 @@ var AnchorPickerLit = class extends LitElement {
3889
4119
  // The component itself renders nothing β€” all overlay HTML lives in _portalDiv
3890
4120
  // (a div appended to document.body), managed by _syncPortal().
3891
4121
  render() {
3892
- return nothing2;
4122
+ return nothing3;
3893
4123
  }
3894
4124
  _overlayTemplate() {
3895
- if (!this.isActive) return nothing2;
4125
+ if (!this.isActive) return nothing3;
3896
4126
  const hovered = this._hoveredElement;
3897
4127
  const rect = hovered?.getBoundingClientRect() ?? null;
3898
- return html2`
4128
+ return html3`
3899
4129
  <div
3900
4130
  data-syntro-anchor-picker
3901
4131
  style=${styleMap({
@@ -3917,7 +4147,7 @@ var AnchorPickerLit = class extends LitElement {
3917
4147
  ></div>
3918
4148
 
3919
4149
  <!-- Element highlight -->
3920
- ${hovered && rect ? html2`<div
4150
+ ${hovered && rect ? html3`<div
3921
4151
  style=${styleMap({
3922
4152
  position: "fixed",
3923
4153
  left: `${rect.left - 2}px`,
@@ -3931,10 +4161,10 @@ var AnchorPickerLit = class extends LitElement {
3931
4161
  pointerEvents: "none",
3932
4162
  transition: "all 0.1s ease-out"
3933
4163
  })}
3934
- ></div>` : nothing2}
4164
+ ></div>` : nothing3}
3935
4165
 
3936
4166
  <!-- Element info tooltip near hovered element -->
3937
- ${hovered && rect ? html2`<div
4167
+ ${hovered && rect ? html3`<div
3938
4168
  class="se-text-xs"
3939
4169
  style=${styleMap({
3940
4170
  position: "fixed",
@@ -3983,7 +4213,7 @@ var AnchorPickerLit = class extends LitElement {
3983
4213
  >
3984
4214
  ${getElementDescription2(hovered)}
3985
4215
  </div>
3986
- </div>` : nothing2}
4216
+ </div>` : nothing3}
3987
4217
  </div>
3988
4218
  `;
3989
4219
  }
@@ -4001,8 +4231,8 @@ if (!customElements.get("se-anchor-picker")) {
4001
4231
  }
4002
4232
 
4003
4233
  // ../../shared-editor-ui/src/components/AnchorPillLit.ts
4004
- import { html as html3, LitElement as LitElement2 } from "lit";
4005
- var AnchorPillLit = class extends LitElement2 {
4234
+ import { html as html4, LitElement as LitElement3 } from "lit";
4235
+ var AnchorPillLit = class extends LitElement3 {
4006
4236
  constructor() {
4007
4237
  super(...arguments);
4008
4238
  this.state = "missing";
@@ -4041,7 +4271,7 @@ var AnchorPillLit = class extends LitElement2 {
4041
4271
  const redCls = "se-border-red-4/60 se-bg-red-4/10 se-text-red-5 se-cursor-not-allowed";
4042
4272
  const testid = `${this.testidPrefix}-${this.testidKey}`;
4043
4273
  if (this.state === "locate") {
4044
- return html3`<button
4274
+ return html4`<button
4045
4275
  type="button"
4046
4276
  data-testid=${testid}
4047
4277
  data-state="locate"
@@ -4053,7 +4283,7 @@ var AnchorPillLit = class extends LitElement2 {
4053
4283
  </button>`;
4054
4284
  }
4055
4285
  if (this.state === "navigate" && this.route) {
4056
- return html3`<button
4286
+ return html4`<button
4057
4287
  type="button"
4058
4288
  data-testid=${testid}
4059
4289
  data-state="navigate"
@@ -4064,7 +4294,7 @@ var AnchorPillLit = class extends LitElement2 {
4064
4294
  Go to ${this.route}
4065
4295
  </button>`;
4066
4296
  }
4067
- return html3`<span
4297
+ return html4`<span
4068
4298
  data-testid=${testid}
4069
4299
  data-state="missing"
4070
4300
  title="Anchor not available on this page"
@@ -4088,8 +4318,8 @@ if (!customElements.get("se-anchor-pill")) {
4088
4318
  }
4089
4319
 
4090
4320
  // ../../shared-editor-ui/src/components/EditorCardLit.ts
4091
- import { html as html4, LitElement as LitElement3 } from "lit";
4092
- var EditorCardLit = class extends LitElement3 {
4321
+ import { html as html5, LitElement as LitElement4 } from "lit";
4322
+ var EditorCardLit = class extends LitElement4 {
4093
4323
  constructor() {
4094
4324
  super(...arguments);
4095
4325
  this.itemKey = "";
@@ -4137,7 +4367,7 @@ var EditorCardLit = class extends LitElement3 {
4137
4367
  const bgCls = "bg-white/[0.02]";
4138
4368
  const colorCls = "text-slate-200";
4139
4369
  const interactiveCls = this.clickable ? "cursor-pointer hover:border-white/20 hover:bg-white/[0.04] transition-colors" : "";
4140
- return html4`
4370
+ return html5`
4141
4371
  <style>
4142
4372
  :host { display: block; }
4143
4373
  .card {
@@ -4189,7 +4419,7 @@ if (!customElements.get("se-editor-card")) {
4189
4419
  }
4190
4420
 
4191
4421
  // ../../shared-editor-ui/src/components/EditorPanelShellLit.ts
4192
- import { html as html5, LitElement as LitElement4, nothing as nothing3 } from "lit";
4422
+ import { html as html6, LitElement as LitElement5, nothing as nothing4 } from "lit";
4193
4423
  import { styleMap as styleMap2 } from "lit/directives/style-map.js";
4194
4424
  var STORAGE_KEY = "syntro:editor-panel";
4195
4425
  var MIN_WIDTH2 = panel_shell_default.behavior.minWidth;
@@ -4349,7 +4579,7 @@ var RESIZE_HANDLES2 = [
4349
4579
  cursor: "nesw-resize"
4350
4580
  }
4351
4581
  ];
4352
- var syntroLogoSvg = html5`<svg
4582
+ var syntroLogoSvg = html6`<svg
4353
4583
  aria-hidden="true"
4354
4584
  width="28"
4355
4585
  height="18"
@@ -4369,7 +4599,7 @@ var syntroLogoSvg = html5`<svg
4369
4599
  </clipPath>
4370
4600
  </defs>
4371
4601
  </svg>`;
4372
- var EditorPanelShellLit = class extends LitElement4 {
4602
+ var EditorPanelShellLit = class extends LitElement5 {
4373
4603
  constructor() {
4374
4604
  super(...arguments);
4375
4605
  this.isOpen = false;
@@ -4611,17 +4841,17 @@ var EditorPanelShellLit = class extends LitElement4 {
4611
4841
  }
4612
4842
  // ---- RENDER ----
4613
4843
  render() {
4614
- return html5`
4615
- ${this.isOpen ? html5`<div
4844
+ return html6`
4845
+ ${this.isOpen ? html6`<div
4616
4846
  data-syntro-editor-panel
4617
4847
  data-syntro-editor-ui="panel"
4618
4848
  class=${this._getPanelClasses()}
4619
4849
  style=${styleMap2(this._getPanelStyles())}
4620
- ${this.panelId ? html5`` : nothing3}
4621
- id=${this.panelId ?? nothing3}
4850
+ ${this.panelId ? html6`` : nothing4}
4851
+ id=${this.panelId ?? nothing4}
4622
4852
  >
4623
4853
  ${RESIZE_HANDLES2.map(
4624
- (h) => html5`<div
4854
+ (h) => html6`<div
4625
4855
  data-syntro-editor-ui="resize-${h.dir}"
4626
4856
  data-resize-dir=${h.dir}
4627
4857
  @pointerdown=${this._handleResizePointerDown}
@@ -4637,7 +4867,7 @@ var EditorPanelShellLit = class extends LitElement4 {
4637
4867
  ></div>`
4638
4868
  )}
4639
4869
  <slot></slot>
4640
- </div>` : nothing3}
4870
+ </div>` : nothing4}
4641
4871
 
4642
4872
  <div
4643
4873
  class="syntro-editor-scope"
@@ -4670,9 +4900,9 @@ if (!customElements.get("se-editor-panel-shell")) {
4670
4900
  }
4671
4901
 
4672
4902
  // ../../shared-editor-ui/src/components/EditorTextareaLit.ts
4673
- import { html as html6, LitElement as LitElement5 } from "lit";
4903
+ import { html as html7, LitElement as LitElement6 } from "lit";
4674
4904
  var _textareaIdCounter = 0;
4675
- var EditorTextareaLit = class extends LitElement5 {
4905
+ var EditorTextareaLit = class extends LitElement6 {
4676
4906
  constructor() {
4677
4907
  super();
4678
4908
  this.disabled = false;
@@ -4725,9 +4955,9 @@ var EditorTextareaLit = class extends LitElement5 {
4725
4955
  "disabled:se-bg-input-field-bg-disabled disabled:se-cursor-not-allowed disabled:se-opacity-50",
4726
4956
  this.textareaClass || ""
4727
4957
  ].filter(Boolean).join(" ");
4728
- return html6`
4958
+ return html7`
4729
4959
  <div>
4730
- ${this.label ? html6`<label
4960
+ ${this.label ? html7`<label
4731
4961
  for=${id}
4732
4962
  class="se-text-sm se-font-medium se-text-input-field-text-label se-mb-1 se-block"
4733
4963
  >${this.label}</label>` : ""}
@@ -4764,9 +4994,9 @@ if (!customElements.get("se-editor-textarea")) {
4764
4994
  }
4765
4995
 
4766
4996
  // ../../shared-editor-ui/src/components/ElementHighlightLit.ts
4767
- import { html as html7, LitElement as LitElement6, nothing as nothing4 } from "lit";
4997
+ import { html as html8, LitElement as LitElement7, nothing as nothing5 } from "lit";
4768
4998
  import { styleMap as styleMap3 } from "lit/directives/style-map.js";
4769
- var ElementHighlightLit = class extends LitElement6 {
4999
+ var ElementHighlightLit = class extends LitElement7 {
4770
5000
  constructor() {
4771
5001
  super(...arguments);
4772
5002
  this.element = null;
@@ -4873,7 +5103,7 @@ var ElementHighlightLit = class extends LitElement6 {
4873
5103
  // ---- RENDER ----
4874
5104
  render() {
4875
5105
  const rect = this._rect;
4876
- if (!rect) return nothing4;
5106
+ if (!rect) return nothing5;
4877
5107
  const el = this.element;
4878
5108
  const hasInteraction = this.interactive || this.showRemove;
4879
5109
  let dimensionsLabel = null;
@@ -4885,14 +5115,14 @@ var ElementHighlightLit = class extends LitElement6 {
4885
5115
  }
4886
5116
  const displayLabel = this.label || dimensionsLabel;
4887
5117
  const labelBg = this.showDimensions ? `${this.color.replace(")", ",0.85)").replace("rgb(", "rgba(")}` : this.color;
4888
- return html7`
5118
+ return html8`
4889
5119
  <div
4890
5120
  data-syntro-highlight
4891
5121
  data-syntro-editor-ui="highlight"
4892
- role=${this.interactive ? "button" : nothing4}
4893
- tabindex=${this.interactive ? "0" : nothing4}
4894
- @click=${this.interactive ? this._handleClick : nothing4}
4895
- @keydown=${this.interactive ? this._handleKeyDown : nothing4}
5122
+ role=${this.interactive ? "button" : nothing5}
5123
+ tabindex=${this.interactive ? "0" : nothing5}
5124
+ @click=${this.interactive ? this._handleClick : nothing5}
5125
+ @keydown=${this.interactive ? this._handleKeyDown : nothing5}
4896
5126
  style=${styleMap3({
4897
5127
  position: "fixed",
4898
5128
  top: `${rect.top - this.padding}px`,
@@ -4909,7 +5139,7 @@ var ElementHighlightLit = class extends LitElement6 {
4909
5139
  boxSizing: "border-box"
4910
5140
  })}
4911
5141
  >
4912
- ${displayLabel ? html7`<div
5142
+ ${displayLabel ? html8`<div
4913
5143
  data-syntro-highlight-label
4914
5144
  data-syntro-editor-ui="highlight-label"
4915
5145
  class="se-text-xs"
@@ -4932,7 +5162,7 @@ var ElementHighlightLit = class extends LitElement6 {
4932
5162
  >
4933
5163
  <slot name="label-icon"></slot>
4934
5164
  ${displayLabel}
4935
- ${this.showRemove ? html7`<button
5165
+ ${this.showRemove ? html8`<button
4936
5166
  type="button"
4937
5167
  class="se-text-xs"
4938
5168
  data-syntro-highlight-remove
@@ -4954,8 +5184,8 @@ var ElementHighlightLit = class extends LitElement6 {
4954
5184
  })}
4955
5185
  >
4956
5186
  \u00d7
4957
- </button>` : nothing4}
4958
- </div>` : nothing4}
5187
+ </button>` : nothing5}
5188
+ </div>` : nothing5}
4959
5189
  </div>
4960
5190
  `;
4961
5191
  }
@@ -4980,8 +5210,8 @@ if (!customElements.get("se-element-highlight")) {
4980
5210
  }
4981
5211
 
4982
5212
  // ../../shared-editor-ui/src/components/EmptyStateLit.ts
4983
- import { html as html8, LitElement as LitElement7 } from "lit";
4984
- var EmptyStateLit = class extends LitElement7 {
5213
+ import { html as html9, LitElement as LitElement8 } from "lit";
5214
+ var EmptyStateLit = class extends LitElement8 {
4985
5215
  constructor() {
4986
5216
  super(...arguments);
4987
5217
  this.message = "";
@@ -4990,7 +5220,7 @@ var EmptyStateLit = class extends LitElement7 {
4990
5220
  return this;
4991
5221
  }
4992
5222
  render() {
4993
- return html8`
5223
+ return html9`
4994
5224
  <div class="se-text-center se-py-8 se-px-4 se-text-text-secondary se-text-sm">
4995
5225
  ${this.message}
4996
5226
  </div>
@@ -5005,8 +5235,8 @@ if (!customElements.get("se-empty-state")) {
5005
5235
  }
5006
5236
 
5007
5237
  // ../../shared-editor-ui/src/components/GroupHeaderLit.ts
5008
- import { html as html9, LitElement as LitElement8 } from "lit";
5009
- var GroupHeaderLit = class extends LitElement8 {
5238
+ import { html as html10, LitElement as LitElement9 } from "lit";
5239
+ var GroupHeaderLit = class extends LitElement9 {
5010
5240
  constructor() {
5011
5241
  super(...arguments);
5012
5242
  this.label = "";
@@ -5020,7 +5250,7 @@ var GroupHeaderLit = class extends LitElement8 {
5020
5250
  "se-text-xs se-font-bold se-text-text-primary se-uppercase se-tracking-wide se-py-1 se-pb-2 se-flex se-items-center se-justify-between",
5021
5251
  this.headerClass || ""
5022
5252
  ].filter(Boolean).join(" ");
5023
- return html9`
5253
+ return html10`
5024
5254
  <div class=${classes}>
5025
5255
  <span>${this.label}</span>
5026
5256
  <span class="se-text-xs se-text-text-secondary se-bg-badge-slate-bg se-px-1.5 se-py-0.5 se-rounded-lg">
@@ -5039,6 +5269,811 @@ if (!customElements.get("se-group-header")) {
5039
5269
  customElements.define("se-group-header", GroupHeaderLit);
5040
5270
  }
5041
5271
 
5272
+ // ../../shared-editor-ui/src/components/TileChromeEditorLit.ts
5273
+ import { css as css2, html as html11, LitElement as LitElement10, nothing as nothing6 } from "lit";
5274
+ var EMOJI_LIST2 = [
5275
+ "\u{1F4B5}",
5276
+ "\u{1F4B0}",
5277
+ "\u{1F3DB}\uFE0F",
5278
+ "\u23ED\uFE0F",
5279
+ "\u27A1\uFE0F",
5280
+ "\u{1F4A1}",
5281
+ "\u{1F4CB}",
5282
+ "\u2705",
5283
+ "\u26A0\uFE0F",
5284
+ "\u{1F6E1}\uFE0F",
5285
+ "\u{1F4C8}",
5286
+ "\u{1F52C}",
5287
+ "\u{1F48A}",
5288
+ "\u{1F4C4}",
5289
+ "\u{1F9EA}",
5290
+ "\u{1F501}",
5291
+ "\u{1F9E0}",
5292
+ "\u{1F319}",
5293
+ "\u{1F4E6}",
5294
+ "\u{1F69A}",
5295
+ "\u{1F331}",
5296
+ "\u26A1",
5297
+ "\u{1F525}",
5298
+ "\u{1F333}",
5299
+ "\u{1F33F}",
5300
+ "\u2753",
5301
+ "\u{1F9ED}",
5302
+ "\u{1F4DD}",
5303
+ "\u{1F3AF}",
5304
+ "\u{1F3C6}",
5305
+ "\u2728",
5306
+ "\u{1F4AC}",
5307
+ "\u{1F3AE}",
5308
+ "\u23F1\uFE0F",
5309
+ "\u{1F4D6}",
5310
+ "\u{1F514}",
5311
+ "\u{1F393}",
5312
+ "\u23F0",
5313
+ "\u{1F504}",
5314
+ "\u{1F464}",
5315
+ "\u{1F3E0}",
5316
+ "\u{1F6D2}",
5317
+ "\u{1F4CA}",
5318
+ "\u{1F4C9}",
5319
+ "\u{1F967}",
5320
+ "\u{1F4B9}",
5321
+ "\u{1F321}\uFE0F"
5322
+ ];
5323
+ var TileChromeEditorLit2 = class extends LitElement10 {
5324
+ constructor() {
5325
+ super(...arguments);
5326
+ this.tileMeta = { title: "", subtitle: "", icon: "" };
5327
+ this.onChange = () => {
5328
+ };
5329
+ this._pickerOpen = false;
5330
+ }
5331
+ _patch(field, value) {
5332
+ const updated = { ...this.tileMeta, [field]: value };
5333
+ this.tileMeta = updated;
5334
+ this.onChange(updated);
5335
+ }
5336
+ _selectEmoji(emoji) {
5337
+ const value = this.tileMeta.icon === emoji ? "" : emoji;
5338
+ this._patch("icon", value);
5339
+ }
5340
+ render() {
5341
+ return html11`
5342
+ <form @submit=${(e) => e.preventDefault()}>
5343
+ <label>
5344
+ <span>Title</span>
5345
+ <input
5346
+ name="title"
5347
+ type="text"
5348
+ .value=${this.tileMeta.title}
5349
+ @input=${(e) => this._patch("title", e.target.value)}
5350
+ />
5351
+ </label>
5352
+
5353
+ <label>
5354
+ <span>Subtitle</span>
5355
+ <input
5356
+ name="subtitle"
5357
+ type="text"
5358
+ .value=${this.tileMeta.subtitle}
5359
+ placeholder="Optional"
5360
+ @input=${(e) => this._patch("subtitle", e.target.value)}
5361
+ />
5362
+ </label>
5363
+
5364
+ <div class="icon-section">
5365
+ <span>Icon</span>
5366
+ <button
5367
+ type="button"
5368
+ class="icon-toggle"
5369
+ data-emoji-toggle
5370
+ @click=${() => {
5371
+ this._pickerOpen = !this._pickerOpen;
5372
+ }}
5373
+ >
5374
+ ${this.tileMeta.icon ? html11`<span style="font-size: 20px">${this.tileMeta.icon}</span>` : html11`<span style="color: var(--syntro-text-tertiary, #87919f)">Choose icon…</span>`}
5375
+ </button>
5376
+
5377
+ ${this._pickerOpen ? html11`
5378
+ <div data-emoji-grid class="emoji-grid">
5379
+ ${EMOJI_LIST2.map(
5380
+ (emoji) => html11`
5381
+ <button
5382
+ type="button"
5383
+ data-emoji=${emoji}
5384
+ class=${this.tileMeta.icon === emoji ? "selected" : ""}
5385
+ @click=${() => this._selectEmoji(emoji)}
5386
+ title=${emoji}
5387
+ >${emoji}</button>
5388
+ `
5389
+ )}
5390
+ </div>
5391
+ ` : nothing6}
5392
+ </div>
5393
+ </form>
5394
+ `;
5395
+ }
5396
+ };
5397
+ TileChromeEditorLit2.styles = css2`
5398
+ :host {
5399
+ display: block;
5400
+ width: 100%;
5401
+ font-family: system-ui, -apple-system, sans-serif;
5402
+ }
5403
+ form {
5404
+ display: flex;
5405
+ flex-direction: column;
5406
+ gap: 16px;
5407
+ }
5408
+ label {
5409
+ display: flex;
5410
+ flex-direction: column;
5411
+ gap: 6px;
5412
+ }
5413
+ label > span {
5414
+ font-size: 13px;
5415
+ font-weight: 500;
5416
+ color: var(--syntro-text-secondary, #a8afba);
5417
+ }
5418
+ input[type='text'] {
5419
+ width: 100%;
5420
+ box-sizing: border-box;
5421
+ padding: 8px 12px;
5422
+ border-radius: 6px;
5423
+ border: 1px solid var(--syntro-input-field-border-default, #2b333f);
5424
+ background: var(--syntro-input-field-bg-default, #0e1114);
5425
+ color: var(--syntro-text-primary, #cbd0d7);
5426
+ font-size: 14px;
5427
+ font-family: inherit;
5428
+ outline: none;
5429
+ }
5430
+ input[type='text']:focus {
5431
+ border-color: var(--syntro-input-field-border-selected, #b72e2a);
5432
+ box-shadow: var(--syntro-focus-ring-primary, 0 0 0 4px rgba(221, 109, 105, 0.25));
5433
+ }
5434
+ .icon-section {
5435
+ display: flex;
5436
+ flex-direction: column;
5437
+ gap: 6px;
5438
+ }
5439
+ .icon-section > span {
5440
+ font-size: 13px;
5441
+ font-weight: 500;
5442
+ color: var(--syntro-text-secondary, #a8afba);
5443
+ }
5444
+ .icon-toggle {
5445
+ display: inline-flex;
5446
+ align-items: center;
5447
+ gap: 8px;
5448
+ padding: 8px 12px;
5449
+ border-radius: 6px;
5450
+ border: 1px solid var(--syntro-input-field-border-default, #2b333f);
5451
+ background: var(--syntro-input-field-bg-default, #0e1114);
5452
+ color: var(--syntro-text-primary, #cbd0d7);
5453
+ font-size: 14px;
5454
+ cursor: pointer;
5455
+ font-family: inherit;
5456
+ }
5457
+ .icon-toggle:hover {
5458
+ border-color: var(--syntro-input-field-border-selected, #b72e2a);
5459
+ }
5460
+ .emoji-grid {
5461
+ display: grid;
5462
+ grid-template-columns: repeat(8, 1fr);
5463
+ gap: 4px;
5464
+ padding: 8px;
5465
+ margin-top: 4px;
5466
+ background: var(--syntro-background-secondary, #07080a);
5467
+ border: 1px solid var(--syntro-input-field-border-default, #2b333f);
5468
+ border-radius: 8px;
5469
+ max-height: 200px;
5470
+ overflow-y: auto;
5471
+ }
5472
+ .emoji-grid button {
5473
+ display: flex;
5474
+ align-items: center;
5475
+ justify-content: center;
5476
+ width: 36px;
5477
+ height: 36px;
5478
+ border: 1px solid transparent;
5479
+ border-radius: 6px;
5480
+ background: transparent;
5481
+ font-size: 18px;
5482
+ cursor: pointer;
5483
+ padding: 0;
5484
+ transition: background 100ms ease, border-color 100ms ease;
5485
+ }
5486
+ .emoji-grid button:hover {
5487
+ background: rgba(183, 46, 42, 0.1);
5488
+ border-color: rgba(183, 46, 42, 0.3);
5489
+ }
5490
+ .emoji-grid button.selected {
5491
+ background: rgba(183, 46, 42, 0.2);
5492
+ border-color: var(--syntro-button-primary-bg-default, #b72e2a);
5493
+ }
5494
+ `;
5495
+ TileChromeEditorLit2.properties = {
5496
+ tileMeta: { attribute: false },
5497
+ onChange: { attribute: false },
5498
+ _pickerOpen: { state: true }
5499
+ };
5500
+ if (!customElements.get("syntro-tile-chrome-editor")) {
5501
+ customElements.define("syntro-tile-chrome-editor", TileChromeEditorLit2);
5502
+ }
5503
+
5504
+ // src/nav-item-editor.ts
5505
+ import { css as css3, html as html12, LitElement as LitElement11, nothing as nothing7 } from "lit";
5506
+ var NavItemEditorLit = class extends LitElement11 {
5507
+ constructor() {
5508
+ super(...arguments);
5509
+ this.itemId = "";
5510
+ this.appConfig = {
5511
+ expandBehavior: "single",
5512
+ theme: "auto",
5513
+ actions: []
5514
+ };
5515
+ this.onChange = () => {
5516
+ };
5517
+ }
5518
+ _findItem() {
5519
+ return this.appConfig.actions.find(
5520
+ (a) => a.kind === "nav:tip" && a.config.id === this.itemId
5521
+ );
5522
+ }
5523
+ _patchField(field, value) {
5524
+ const next = {
5525
+ ...this.appConfig,
5526
+ actions: this.appConfig.actions.map(
5527
+ (a) => a.kind === "nav:tip" && a.config.id === this.itemId ? { ...a, config: { ...a.config, [field]: value } } : a
5528
+ )
5529
+ };
5530
+ this.onChange(next);
5531
+ }
5532
+ _patchExternal(value) {
5533
+ const next = {
5534
+ ...this.appConfig,
5535
+ actions: this.appConfig.actions.map(
5536
+ (a) => a.kind === "nav:tip" && a.config.id === this.itemId ? { ...a, config: { ...a.config, external: value } } : a
5537
+ )
5538
+ };
5539
+ this.onChange(next);
5540
+ }
5541
+ render() {
5542
+ const item = this._findItem();
5543
+ if (!item) {
5544
+ return html12`<p>Item not found</p>`;
5545
+ }
5546
+ const tip = item;
5547
+ return html12`
5548
+ <form @submit=${(e) => e.preventDefault()}>
5549
+ <div>
5550
+ <label>
5551
+ <span>Title</span>
5552
+ <input
5553
+ name="title"
5554
+ type="text"
5555
+ .value=${tip.config.title ?? ""}
5556
+ @input=${(e) => this._patchField("title", e.target.value)}
5557
+ />
5558
+ </label>
5559
+ </div>
5560
+
5561
+ <div>
5562
+ <label>
5563
+ <span>Description</span>
5564
+ <input
5565
+ name="description"
5566
+ type="text"
5567
+ .value=${tip.config.description ?? ""}
5568
+ @input=${(e) => this._patchField("description", e.target.value)}
5569
+ />
5570
+ </label>
5571
+ </div>
5572
+
5573
+ <div>
5574
+ <label>
5575
+ <span>Link URL</span>
5576
+ <input
5577
+ name="href"
5578
+ type="text"
5579
+ .value=${tip.config.href ?? ""}
5580
+ placeholder="Optional"
5581
+ @input=${(e) => this._patchField("href", e.target.value)}
5582
+ />
5583
+ </label>
5584
+ </div>
5585
+
5586
+ <div>
5587
+ <label>
5588
+ <span>Icon</span>
5589
+ <input
5590
+ name="icon"
5591
+ type="text"
5592
+ .value=${tip.config.icon ?? ""}
5593
+ placeholder="e.g., 🧭"
5594
+ @input=${(e) => this._patchField("icon", e.target.value)}
5595
+ />
5596
+ </label>
5597
+ </div>
5598
+
5599
+ <div>
5600
+ <label>
5601
+ <span>Category</span>
5602
+ <input
5603
+ name="category"
5604
+ type="text"
5605
+ .value=${tip.config.category ?? ""}
5606
+ placeholder="Optional"
5607
+ @input=${(e) => this._patchField("category", e.target.value)}
5608
+ />
5609
+ </label>
5610
+ </div>
5611
+
5612
+ <div>
5613
+ <label class="checkbox-label">
5614
+ <input
5615
+ name="external"
5616
+ type="checkbox"
5617
+ .checked=${tip.config.external ?? false}
5618
+ @change=${(e) => this._patchExternal(e.target.checked)}
5619
+ />
5620
+ <span>Open in new tab</span>
5621
+ </label>
5622
+ </div>
5623
+
5624
+ ${tip.rationale ? html12`
5625
+ <div>
5626
+ <span>AI Rationale</span>
5627
+ <div data-rationale>${tip.rationale.why}</div>
5628
+ </div>
5629
+ ` : nothing7}
5630
+ </form>
5631
+ `;
5632
+ }
5633
+ };
5634
+ NavItemEditorLit.styles = css3`
5635
+ :host {
5636
+ display: block;
5637
+ width: 100%;
5638
+ font-family: system-ui, -apple-system, sans-serif;
5639
+ }
5640
+ form {
5641
+ display: flex;
5642
+ flex-direction: column;
5643
+ gap: 16px;
5644
+ }
5645
+ label {
5646
+ display: flex;
5647
+ flex-direction: column;
5648
+ gap: 6px;
5649
+ }
5650
+ label > span {
5651
+ font-size: 13px;
5652
+ font-weight: 500;
5653
+ color: var(--syntro-text-secondary, #a8afba);
5654
+ }
5655
+ input[type='text'] {
5656
+ width: 100%;
5657
+ box-sizing: border-box;
5658
+ padding: 8px 12px;
5659
+ border-radius: 6px;
5660
+ border: 1px solid var(--syntro-input-field-border-default, #2b333f);
5661
+ background: var(--syntro-input-field-bg-default, #0e1114);
5662
+ color: var(--syntro-text-primary, #cbd0d7);
5663
+ font-size: 14px;
5664
+ font-family: inherit;
5665
+ outline: none;
5666
+ }
5667
+ input[type='text']:focus {
5668
+ border-color: var(--syntro-input-field-border-selected, #b72e2a);
5669
+ box-shadow: var(--syntro-focus-ring-primary, 0 0 0 4px rgba(221, 109, 105, 0.25));
5670
+ }
5671
+ .checkbox-label {
5672
+ flex-direction: row;
5673
+ align-items: center;
5674
+ }
5675
+ .checkbox-label input[type='checkbox'] {
5676
+ width: 16px;
5677
+ height: 16px;
5678
+ accent-color: var(--syntro-button-primary-bg-default, #b72e2a);
5679
+ }
5680
+ [data-rationale] {
5681
+ font-size: 13px;
5682
+ color: var(--syntro-text-tertiary, #87919f);
5683
+ padding: 8px 12px;
5684
+ background: var(--syntro-background-secondary, #07080a);
5685
+ border-radius: 6px;
5686
+ }
5687
+ `;
5688
+ NavItemEditorLit.properties = {
5689
+ itemId: { type: String, attribute: "item-id" },
5690
+ appConfig: { attribute: false },
5691
+ onChange: { attribute: false }
5692
+ };
5693
+ customElements.define("syntro-nav-item-editor", NavItemEditorLit);
5694
+
5695
+ // src/NavWidgetLit.editable.ts
5696
+ import { html as html13, LitElement as LitElement12, nothing as nothing8 } from "lit";
5697
+ import { styleMap as styleMap4 } from "lit/directives/style-map.js";
5698
+ function sm(styles) {
5699
+ return styles;
5700
+ }
5701
+ var ADAPTIVE_ID = "adaptive-nav:tips";
5702
+ var SORTABLE_STYLE_ID = "syntro-sortable-drag-styles";
5703
+ function ensureSortableStyles() {
5704
+ if (document.getElementById(SORTABLE_STYLE_ID)) return;
5705
+ const style = document.createElement("style");
5706
+ style.id = SORTABLE_STYLE_ID;
5707
+ style.textContent = `
5708
+ .syntro-sortable-dragging {
5709
+ opacity: 0.4;
5710
+ background: rgba(106, 89, 206, 0.08) !important;
5711
+ box-shadow: inset 0 0 0 1px rgba(106, 89, 206, 0.2);
5712
+ transition: opacity 150ms ease, background 150ms ease;
5713
+ }
5714
+ .syntro-sortable-drag-over {
5715
+ background: rgba(106, 89, 206, 0.04) !important;
5716
+ transition: background 150ms ease;
5717
+ }
5718
+ .syntro-sortable-active [data-drag-handle] {
5719
+ cursor: grabbing;
5720
+ }
5721
+ `;
5722
+ document.head.appendChild(style);
5723
+ }
5724
+ var ROW_STYLE = {
5725
+ position: "relative",
5726
+ display: "flex",
5727
+ alignItems: "center",
5728
+ padding: "12px 16px",
5729
+ cursor: "default",
5730
+ userSelect: "none",
5731
+ borderBottom: "1px solid rgba(0, 0, 0, 0.06)",
5732
+ transition: "background 0.15s ease"
5733
+ };
5734
+ var ROW_HOVER_STYLE = {
5735
+ ...ROW_STYLE,
5736
+ background: "rgba(106, 89, 206, 0.06)"
5737
+ };
5738
+ var CONTENT_STYLE = {
5739
+ flex: "1",
5740
+ minWidth: "0"
5741
+ };
5742
+ var TITLE_STYLE = {
5743
+ fontWeight: "500",
5744
+ fontSize: "14px",
5745
+ lineHeight: "1.4",
5746
+ color: "inherit",
5747
+ display: "block"
5748
+ };
5749
+ var DESCRIPTION_STYLE = {
5750
+ fontSize: "12px",
5751
+ lineHeight: "1.4",
5752
+ color: "rgba(0, 0, 0, 0.5)",
5753
+ display: "block",
5754
+ marginTop: "2px",
5755
+ overflow: "hidden",
5756
+ textOverflow: "ellipsis",
5757
+ whiteSpace: "nowrap"
5758
+ };
5759
+ var PENCIL_STYLE = {
5760
+ flexShrink: "0",
5761
+ marginLeft: "8px",
5762
+ padding: "4px 6px",
5763
+ background: "transparent",
5764
+ border: "1px solid rgba(106, 89, 206, 0.3)",
5765
+ borderRadius: "4px",
5766
+ cursor: "pointer",
5767
+ fontSize: "12px",
5768
+ opacity: "0",
5769
+ transition: "opacity 0.15s ease",
5770
+ color: "rgb(106, 89, 206)",
5771
+ display: "flex",
5772
+ alignItems: "center",
5773
+ justifyContent: "center"
5774
+ };
5775
+ var PENCIL_VISIBLE_STYLE = {
5776
+ ...PENCIL_STYLE,
5777
+ opacity: "1"
5778
+ };
5779
+ var DRAG_HANDLE_STYLE = {
5780
+ flexShrink: "0",
5781
+ marginRight: "8px",
5782
+ cursor: "grab",
5783
+ fontSize: "14px",
5784
+ color: "rgba(0, 0, 0, 0.3)",
5785
+ lineHeight: "1"
5786
+ };
5787
+ var CONTAINER_STYLE = {
5788
+ borderRadius: "8px",
5789
+ overflow: "hidden",
5790
+ border: "1px solid rgba(0, 0, 0, 0.08)",
5791
+ background: "#fff"
5792
+ };
5793
+ var EMPTY_STYLE = {
5794
+ padding: "16px",
5795
+ color: "rgba(0, 0, 0, 0.4)",
5796
+ fontSize: "13px",
5797
+ textAlign: "center"
5798
+ };
5799
+ var TILE_EDIT_BTN_STYLE = {
5800
+ position: "absolute",
5801
+ top: "8px",
5802
+ right: "8px",
5803
+ padding: "4px 6px",
5804
+ background: "transparent",
5805
+ border: "1px solid rgba(106, 89, 206, 0.3)",
5806
+ borderRadius: "4px",
5807
+ cursor: "pointer",
5808
+ fontSize: "12px",
5809
+ opacity: "0",
5810
+ transition: "opacity 0.15s ease",
5811
+ color: "rgb(106, 89, 206)",
5812
+ display: "flex",
5813
+ alignItems: "center",
5814
+ justifyContent: "center",
5815
+ zIndex: "1"
5816
+ };
5817
+ var TILE_EDIT_BTN_VISIBLE_STYLE = {
5818
+ ...TILE_EDIT_BTN_STYLE,
5819
+ opacity: "1"
5820
+ };
5821
+ var NavTipsEditableElement = class extends LitElement12 {
5822
+ constructor() {
5823
+ super(...arguments);
5824
+ // -------------------------------------------------------------------------
5825
+ // Property declarations
5826
+ // -------------------------------------------------------------------------
5827
+ this.navConfig = {
5828
+ expandBehavior: "single",
5829
+ theme: "auto",
5830
+ actions: []
5831
+ };
5832
+ /** Null when loaded without an editor context β€” renders read-only list. */
5833
+ this.controller = null;
5834
+ /**
5835
+ * Host tile id, threaded in via the mountable's `instanceId`. Scopes every
5836
+ * controller call so the right tile is targeted when the canvas has more
5837
+ * than one Nav tile (per-route navs). Empty string when unknown.
5838
+ */
5839
+ this.tileId = "";
5840
+ /**
5841
+ * The `makeSortable` factory to use. Injected by NavWidgetLitEditableMountable
5842
+ * from the editor-sdk bootstrap so there is no direct import from editor-sdk
5843
+ * into this package (which would create a circular dependency).
5844
+ *
5845
+ * Null when running without the editor context (read-only mode).
5846
+ */
5847
+ this.sortable = null;
5848
+ /**
5849
+ * Shared aria-live region from the modal host, threaded in via mount config.
5850
+ * Falls back to a detached element when running outside the editor context.
5851
+ */
5852
+ this.liveRegion = null;
5853
+ this._hoveredId = null;
5854
+ this._containerHovered = false;
5855
+ // -------------------------------------------------------------------------
5856
+ // Private sortable state (Phase 3.3 will wire this)
5857
+ // -------------------------------------------------------------------------
5858
+ this._sortableHandle = null;
5859
+ }
5860
+ // -------------------------------------------------------------------------
5861
+ // Light DOM β€” inherits host-page CSS variables
5862
+ // -------------------------------------------------------------------------
5863
+ createRenderRoot() {
5864
+ return this;
5865
+ }
5866
+ connectedCallback() {
5867
+ super.connectedCallback();
5868
+ ensureSortableStyles();
5869
+ }
5870
+ // -------------------------------------------------------------------------
5871
+ // Lifecycle β€” sortable wiring
5872
+ // -------------------------------------------------------------------------
5873
+ /**
5874
+ * Wire (or re-wire) the sortable whenever the properties it depends on change.
5875
+ * `updated()` fires after every render, including the first, so we don't need
5876
+ * a separate `firstUpdated()` call β€” using `updated()` alone avoids a double
5877
+ * attach on mount (firstUpdated + updated both fire on first render).
5878
+ */
5879
+ updated(changed) {
5880
+ if (changed.has("controller") || changed.has("navConfig") || changed.has("sortable")) {
5881
+ this._sortableHandle?.destroy();
5882
+ this._sortableHandle = null;
5883
+ this._attachSortable();
5884
+ }
5885
+ }
5886
+ disconnectedCallback() {
5887
+ super.disconnectedCallback();
5888
+ this._sortableHandle?.destroy();
5889
+ this._sortableHandle = null;
5890
+ }
5891
+ _attachSortable() {
5892
+ if (!this.controller) return;
5893
+ if (!this.sortable) return;
5894
+ if ((this.navConfig.actions ?? []).length < 2) return;
5895
+ const liveRegion = this.liveRegion ?? document.createElement("div");
5896
+ this._sortableHandle = this.sortable(this, {
5897
+ itemSelector: "[data-nav-editable-row]",
5898
+ handleSelector: "[data-drag-handle]",
5899
+ getItems: () => (this.navConfig.actions ?? []).map((a) => a.config.id),
5900
+ onReorder: (newOrder) => this.controller.reorderItems(ADAPTIVE_ID, newOrder, this.tileId || void 0),
5901
+ liveRegion
5902
+ });
5903
+ }
5904
+ // -------------------------------------------------------------------------
5905
+ // Handlers
5906
+ // -------------------------------------------------------------------------
5907
+ _handleEdit(itemId) {
5908
+ if (!this.controller) return;
5909
+ if (this.controller.isModalOpen()) return;
5910
+ this.controller.editItem(ADAPTIVE_ID, itemId, this.tileId || void 0);
5911
+ }
5912
+ _handlePencilClick(e, itemId) {
5913
+ e.preventDefault();
5914
+ e.stopPropagation();
5915
+ this._handleEdit(itemId);
5916
+ }
5917
+ _handleContainerEdit() {
5918
+ if (!this.controller) return;
5919
+ if (this.controller.isModalOpen()) return;
5920
+ this.controller.editContainer(ADAPTIVE_ID, this.tileId || void 0);
5921
+ }
5922
+ // -------------------------------------------------------------------------
5923
+ // Render helpers
5924
+ // -------------------------------------------------------------------------
5925
+ _renderRow(item, showHandles) {
5926
+ const { id, title, description } = item.config;
5927
+ const isHovered = this._hoveredId === id;
5928
+ const rowStyle = isHovered ? ROW_HOVER_STYLE : ROW_STYLE;
5929
+ const pencilStyle = isHovered ? PENCIL_VISIBLE_STYLE : PENCIL_STYLE;
5930
+ return html13`
5931
+ <div
5932
+ data-nav-editable-row
5933
+ data-item-id=${id}
5934
+ style=${styleMap4(sm(rowStyle))}
5935
+ @mouseenter=${() => {
5936
+ this._hoveredId = id;
5937
+ }}
5938
+ @mouseleave=${() => {
5939
+ this._hoveredId = null;
5940
+ }}
5941
+ >
5942
+ ${showHandles ? html13`
5943
+ <span
5944
+ data-drag-handle
5945
+ style=${styleMap4(sm(DRAG_HANDLE_STYLE))}
5946
+ title="Drag to reorder"
5947
+ aria-hidden="true"
5948
+ >β Ώ</span>
5949
+ ` : nothing8}
5950
+
5951
+ <span style=${styleMap4(sm(CONTENT_STYLE))}>
5952
+ <span style=${styleMap4(sm(TITLE_STYLE))}>${title}</span>
5953
+ ${description ? html13`<span style=${styleMap4(sm(DESCRIPTION_STYLE))}>${description}</span>` : nothing8}
5954
+ </span>
5955
+
5956
+ <button
5957
+ type="button"
5958
+ data-edit-pencil
5959
+ data-item-id=${id}
5960
+ style=${styleMap4(sm(pencilStyle))}
5961
+ title="Edit this item"
5962
+ aria-label="Edit ${title}"
5963
+ @click=${(e) => this._handlePencilClick(e, id)}
5964
+ >✏️</button>
5965
+ </div>
5966
+ `;
5967
+ }
5968
+ // -------------------------------------------------------------------------
5969
+ // Render
5970
+ // -------------------------------------------------------------------------
5971
+ render() {
5972
+ const items = this.navConfig.actions ?? [];
5973
+ const hasController = this.controller !== null;
5974
+ const showHandles = hasController && items.length >= 2;
5975
+ if (items.length === 0) {
5976
+ return html13`
5977
+ <div
5978
+ style=${styleMap4(sm(CONTAINER_STYLE))}
5979
+ data-adaptive-id="nav-editable"
5980
+ data-adaptive-type="adaptive-nav"
5981
+ >
5982
+ <div style=${styleMap4(sm(EMPTY_STYLE))}>
5983
+ No nav tips yet. Add tips in the editor panel.
5984
+ </div>
5985
+ </div>
5986
+ `;
5987
+ }
5988
+ if (hasController) {
5989
+ const editBtnStyle = this._containerHovered ? TILE_EDIT_BTN_VISIBLE_STYLE : TILE_EDIT_BTN_STYLE;
5990
+ return html13`
5991
+ <div
5992
+ style=${styleMap4(sm({ ...CONTAINER_STYLE, position: "relative" }))}
5993
+ data-adaptive-id="nav-editable"
5994
+ data-adaptive-type="adaptive-nav"
5995
+ @mouseenter=${() => {
5996
+ this._containerHovered = true;
5997
+ }}
5998
+ @mouseleave=${() => {
5999
+ this._containerHovered = false;
6000
+ }}
6001
+ >
6002
+ <button
6003
+ type="button"
6004
+ data-settings-btn
6005
+ style=${styleMap4(sm(editBtnStyle))}
6006
+ title="Edit tile settings"
6007
+ aria-label="Edit tile settings"
6008
+ @click=${() => this._handleContainerEdit()}
6009
+ >✏️</button>
6010
+ ${items.map((item) => this._renderRow(item, showHandles))}
6011
+ </div>
6012
+ `;
6013
+ }
6014
+ return html13`
6015
+ <div
6016
+ style=${styleMap4(sm(CONTAINER_STYLE))}
6017
+ data-adaptive-id="nav-editable"
6018
+ data-adaptive-type="adaptive-nav"
6019
+ >
6020
+ ${items.map(
6021
+ (item) => html13`
6022
+ <div
6023
+ style=${styleMap4(sm(ROW_STYLE))}
6024
+ data-nav-tip-id=${item.config.id}
6025
+ >
6026
+ <span style=${styleMap4(sm(CONTENT_STYLE))}>
6027
+ <span style=${styleMap4(sm(TITLE_STYLE))}>${item.config.title}</span>
6028
+ ${item.config.description ? html13`<span style=${styleMap4(sm(DESCRIPTION_STYLE))}>${item.config.description}</span>` : nothing8}
6029
+ </span>
6030
+ </div>
6031
+ `
6032
+ )}
6033
+ </div>
6034
+ `;
6035
+ }
6036
+ };
6037
+ // -------------------------------------------------------------------------
6038
+ // Reactive properties
6039
+ // -------------------------------------------------------------------------
6040
+ NavTipsEditableElement.properties = {
6041
+ navConfig: { attribute: false },
6042
+ controller: { attribute: false },
6043
+ tileId: { attribute: false },
6044
+ // Internal hover state per item id
6045
+ _hoveredId: { state: true },
6046
+ _containerHovered: { state: true }
6047
+ };
6048
+ if (!customElements.get("syntro-nav-tips-editable")) {
6049
+ customElements.define("syntro-nav-tips-editable", NavTipsEditableElement);
6050
+ }
6051
+ var NavWidgetLitEditableMountable = {
6052
+ mount(container, config) {
6053
+ const {
6054
+ instanceId = "",
6055
+ controller = null,
6056
+ sortable = null,
6057
+ liveRegion = null,
6058
+ ...navConfig
6059
+ } = config ?? {
6060
+ expandBehavior: "single",
6061
+ theme: "auto",
6062
+ actions: []
6063
+ };
6064
+ const el = document.createElement("syntro-nav-tips-editable");
6065
+ Object.assign(el, {
6066
+ navConfig,
6067
+ controller,
6068
+ sortable,
6069
+ liveRegion,
6070
+ tileId: instanceId
6071
+ });
6072
+ container.appendChild(el);
6073
+ return () => el.remove();
6074
+ }
6075
+ };
6076
+
5042
6077
  // src/editor.ts
5043
6078
  var getCurrentPath = () => window.location.pathname;
5044
6079
  var routeMatchesCurrent = (route) => {
@@ -5098,7 +6133,7 @@ var runDetection = (items) => {
5098
6133
  for (const item of items) map.set(item.key, detectItem(item));
5099
6134
  return map;
5100
6135
  };
5101
- var NavEditorLit = class extends LitElement9 {
6136
+ var NavEditorLit = class extends LitElement13 {
5102
6137
  constructor() {
5103
6138
  super(...arguments);
5104
6139
  this.config = null;
@@ -5114,15 +6149,6 @@ var NavEditorLit = class extends LitElement9 {
5114
6149
  this._handleItemClick = (key) => {
5115
6150
  this._editingKey = key;
5116
6151
  };
5117
- this._handleFieldChange = (index, field, value) => {
5118
- if (!this.config) return;
5119
- const ownActions = (this.config.actions || []).filter(isOwnAction).slice();
5120
- const tip = { ...ownActions[index], config: { ...ownActions[index].config } };
5121
- tip.config[field] = value;
5122
- ownActions[index] = tip;
5123
- const otherActions = (this.config.actions || []).filter((a) => !isOwnAction(a));
5124
- this._emitConfig({ ...this.config, actions: [...otherActions, ...ownActions] });
5125
- };
5126
6152
  this._handleDelete = (index, e) => {
5127
6153
  e.stopPropagation();
5128
6154
  if (!this.config) return;
@@ -5158,7 +6184,7 @@ var NavEditorLit = class extends LitElement9 {
5158
6184
  // ---- Render ----
5159
6185
  this._renderAnchorButton = (item) => {
5160
6186
  const state = this._detectionMap.get(item.key)?.state ?? "missing";
5161
- return html10`<se-anchor-pill
6187
+ return html14`<se-anchor-pill
5162
6188
  .state=${state}
5163
6189
  .selector=${item.selector}
5164
6190
  .route=${item.route}
@@ -5169,61 +6195,24 @@ var NavEditorLit = class extends LitElement9 {
5169
6195
  ></se-anchor-pill>`;
5170
6196
  };
5171
6197
  this._renderEditMode = (item) => {
5172
- const tip = item.tip;
5173
- return html10`
6198
+ if (!this.config) return nothing9;
6199
+ return html14`
5174
6200
  <div class="se-py-1">
5175
6201
  <div class="se-flex se-items-center se-gap-2 se-mb-3 se-text-[13px] se-font-semibold se-text-text-primary">
5176
6202
  <span>🧭</span>
5177
6203
  <span>${item.summary}</span>
5178
6204
  </div>
5179
-
5180
- <div class="se-mb-3">
5181
- <label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Title</label>
5182
- <input type="text" .value=${tip.config.title}
5183
- @input=${(e) => this._handleFieldChange(item.index, "title", e.target.value)}
5184
- class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
5185
- </div>
5186
-
5187
- <div class="se-mb-3">
5188
- <label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Description</label>
5189
- <input type="text" .value=${tip.config.description}
5190
- @input=${(e) => this._handleFieldChange(item.index, "description", e.target.value)}
5191
- class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
5192
- </div>
5193
-
5194
- <div class="se-mb-3">
5195
- <label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Link URL</label>
5196
- <input type="text" .value=${tip.config.href || ""} placeholder="Optional"
5197
- @input=${(e) => this._handleFieldChange(item.index, "href", e.target.value)}
5198
- class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
5199
- </div>
5200
-
5201
- <div class="se-mb-3">
5202
- <label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Icon</label>
5203
- <input type="text" .value=${tip.config.icon || ""} placeholder="e.g., 🧭"
5204
- @input=${(e) => this._handleFieldChange(item.index, "icon", e.target.value)}
5205
- class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
5206
- </div>
5207
-
5208
- <div class="se-mb-3">
5209
- <label class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">Category</label>
5210
- <input type="text" .value=${tip.config.category || ""} placeholder="Optional"
5211
- @input=${(e) => this._handleFieldChange(item.index, "category", e.target.value)}
5212
- class="se-w-full se-p-2 se-rounded se-border se-border-border-primary se-bg-input-field-bg se-text-text-primary se-text-sm" />
5213
- </div>
5214
-
5215
- ${tip.rationale ? html10`
5216
- <div>
5217
- <span class="se-text-[11px] se-font-semibold se-text-text-secondary se-mb-1 se-block">AI Rationale</span>
5218
- <div class="se-p-2 se-rounded se-border se-border-dashed se-border-border-primary se-bg-card-bg se-text-text-secondary se-text-xs se-mb-2">
5219
- ${tip.rationale.why}
5220
- </div>
5221
- </div>
5222
- ` : nothing5}
6205
+ <syntro-nav-item-editor
6206
+ .itemId=${item.tip.config.id}
6207
+ .appConfig=${this.config}
6208
+ .onChange=${(next) => {
6209
+ this._emitConfig(next);
6210
+ }}
6211
+ ></syntro-nav-item-editor>
5223
6212
  </div>
5224
6213
  `;
5225
6214
  };
5226
- this._renderItemCard = (item) => html10`
6215
+ this._renderItemCard = (item) => html14`
5227
6216
  <div
5228
6217
  data-item-key=${item.key}
5229
6218
  data-card-body
@@ -5237,38 +6226,38 @@ var NavEditorLit = class extends LitElement9 {
5237
6226
  deleteTestid: `delete-nav-${item.key}`,
5238
6227
  deleteLabel: "Delete tip"
5239
6228
  })}
5240
- ${item.description ? html10`<div
6229
+ ${item.description ? html14`<div
5241
6230
  data-testid=${`nav-description-${item.key}`}
5242
6231
  class="se-text-[11px] se-text-text-secondary se-mt-1.5 se-line-clamp-2"
5243
- >${item.description}</div>` : nothing5}
5244
- ${item.trigger !== "All pages" ? html10`
6232
+ >${item.description}</div>` : nothing9}
6233
+ ${item.trigger !== "All pages" ? html14`
5245
6234
  <div
5246
6235
  data-testid=${`nav-trigger-${item.key}`}
5247
6236
  class="se-text-[10px] se-text-text-tertiary se-mt-1"
5248
6237
  >πŸ“ ${item.trigger}</div>
5249
- ` : nothing5}
5250
- ${item.validation && item.validation.length > 0 ? html10`<div
6238
+ ` : nothing9}
6239
+ ${item.validation && item.validation.length > 0 ? html14`<div
5251
6240
  data-testid=${`nav-validation-${item.key}`}
5252
6241
  class="se-mt-1.5 se-flex se-flex-col se-gap-0.5"
5253
6242
  >
5254
6243
  ${item.validation.map(
5255
- (line) => html10`<div
6244
+ (line) => html14`<div
5256
6245
  class="se-text-[10px] se-text-text-tertiary se-flex se-items-start se-gap-1"
5257
6246
  ><span class="se-text-text-tertiary">βœ“</span><span>${line}</span></div>`
5258
6247
  )}
5259
- </div>` : nothing5}
5260
- ${item.rationale ? html10`
6248
+ </div>` : nothing9}
6249
+ ${item.rationale ? html14`
5261
6250
  <div class="se-text-[10px] se-text-text-tertiary se-mt-1">WHY: ${item.rationale}</div>
5262
- ` : nothing5}
6251
+ ` : nothing9}
5263
6252
  </div>
5264
6253
  `;
5265
6254
  this._renderListMode = (items) => {
5266
6255
  if (items.length === 0) {
5267
- return html10`<div class="se-text-center se-py-8 se-px-4 se-text-text-secondary se-text-sm">
6256
+ return html14`<div class="se-text-center se-py-8 se-px-4 se-text-text-secondary se-text-sm">
5268
6257
  No tips configured.
5269
6258
  </div>`;
5270
6259
  }
5271
- return html10`
6260
+ return html14`
5272
6261
  <div class="se-text-[11px] se-font-semibold se-uppercase se-tracking-wider se-text-text-secondary se-mb-2 se-px-1">
5273
6262
  TIPS <span class="se-text-text-tertiary se-font-normal">${items.length}</span>
5274
6263
  </div>
@@ -5301,11 +6290,11 @@ var NavEditorLit = class extends LitElement9 {
5301
6290
  }
5302
6291
  render() {
5303
6292
  if (!this.config) {
5304
- return html10`<div class="se-p-8 se-text-center se-text-text-secondary se-text-sm">Loading...</div>`;
6293
+ return html14`<div class="se-p-8 se-text-center se-text-text-secondary se-text-sm">Loading...</div>`;
5305
6294
  }
5306
6295
  const items = flattenItems(this.config);
5307
6296
  const editItem = this._editingKey !== null ? items.find((it) => it.key === this._editingKey) : null;
5308
- return html10`
6297
+ return html14`
5309
6298
  <div class="se-flex se-flex-col se-h-full">
5310
6299
  <!-- Header (no Back button β€” panel provides that) -->
5311
6300
  <div class="se-px-4 se-pt-3 se-pb-1">
@@ -5316,7 +6305,7 @@ var NavEditorLit = class extends LitElement9 {
5316
6305
  </div>
5317
6306
 
5318
6307
  <div class="se-flex-1 se-overflow-auto se-p-4">
5319
- ${editItem ? html10`
6308
+ ${editItem ? html14`
5320
6309
  <button type="button" @click=${() => {
5321
6310
  this._editingKey = null;
5322
6311
  }}
@@ -5336,8 +6325,37 @@ NavEditorLit.properties = {
5336
6325
  _detectionMap: { state: true }
5337
6326
  };
5338
6327
  customElements.define("se-nav-editor", NavEditorLit);
6328
+ function registerNavEditorFactories(modalHost) {
6329
+ modalHost.registerEditorFactory("adaptive-nav:tips", {
6330
+ item: ({ itemId, appConfig, onChange }) => {
6331
+ const el = document.createElement("syntro-nav-item-editor");
6332
+ el.itemId = itemId;
6333
+ el.appConfig = appConfig;
6334
+ el.onChange = onChange;
6335
+ return el;
6336
+ },
6337
+ container: ({ appConfig, onChange }) => {
6338
+ const meta = appConfig._tileMeta;
6339
+ const tileMeta = {
6340
+ title: meta?.title ?? "",
6341
+ subtitle: meta?.subtitle ?? "",
6342
+ icon: meta?.icon ?? ""
6343
+ };
6344
+ const el = document.createElement("syntro-tile-chrome-editor");
6345
+ el.tileMeta = tileMeta;
6346
+ el.onChange = (next) => {
6347
+ onChange({ ...appConfig, _tileMeta: next });
6348
+ };
6349
+ return el;
6350
+ }
6351
+ });
6352
+ }
5339
6353
  export {
5340
- NavEditorLit
6354
+ NavEditorLit,
6355
+ NavItemEditorLit,
6356
+ NavTipsEditableElement,
6357
+ NavWidgetLitEditableMountable,
6358
+ registerNavEditorFactories
5341
6359
  };
5342
6360
  /*! Bundled license information:
5343
6361