pict-section-prompteditor 1.1.1 → 1.1.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pict-section-prompteditor",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Prompt crafting and management section for Pict: typed prompts with segments (context, request, success criteria), curated word list matrices with weights, a {~WordListEntry:Name~} template expression for weighted-random generation, batch generation with zip download, and a pluggable data provider that defaults to in-memory AppData.",
5
5
  "main": "source/Pict-Section-PromptEditor.js",
6
6
  "files": [
@@ -216,6 +216,16 @@ const _DefaultConfiguration =
216
216
  .pspe-viewer-tools { display: flex; gap: 8px; justify-content: flex-end; padding: 8px 0 2px; }
217
217
 
218
218
  .pspe-rich-host { min-height: 320px; }
219
+
220
+ /* Read mode: a header strip (type + browse actions) above the assembled
221
+ prompt rendered as one markdown document. */
222
+ .pspe-reader-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
223
+ .pspe-reader-type { font-size: 12.5px; color: var(--theme-color-text-muted, #97a1ab); margin-right: auto;
224
+ font-family: var(--theme-typography-family-display, inherit);
225
+ text-transform: var(--theme-typography-display-transform, none);
226
+ letter-spacing: var(--theme-typography-display-tracking, normal); }
227
+ .pspe-reader-body { padding: 4px 18px; }
228
+ .pspe-reader-body h1:first-child, .pspe-reader-body h2:first-child { margin-top: 8px; }
219
229
  `,
220
230
 
221
231
  Templates:
@@ -248,6 +258,7 @@ const _DefaultConfiguration =
248
258
  {~TS:PromptEditor-EmptyNote:Record.EmptySlot~}
249
259
  </div>
250
260
  <div class="pspe-main">
261
+ {~TS:PromptEditor-PromptReader:Record.ReaderSlot~}
251
262
  {~TS:PromptEditor-PromptEditorPanel:Record.EditorSlot~}
252
263
  {~TS:PromptEditor-EmptyNote:Record.NoSelectionSlot~}
253
264
  </div>
@@ -263,6 +274,21 @@ const _DefaultConfiguration =
263
274
  <span class="pspe-rail-item-sub">{~D:Record.TypeName~}</span>
264
275
  </button>`
265
276
  },
277
+ {
278
+ Hash: 'PromptEditor-PromptReader',
279
+ Template: /*html*/`
280
+ <div class="pspe-reader">
281
+ <div class="pspe-reader-head">
282
+ <span class="pspe-reader-type">{~D:Record.TypeName~}</span>
283
+ {~TS:PromptEditor-ReaderActions:Record.ActionsSlot~}
284
+ </div>
285
+ <div class="pspe-viewer pspe-md pspe-reader-body">{~D:Record.MarkdownHtml~}</div>
286
+ </div>`
287
+ },
288
+ {
289
+ Hash: 'PromptEditor-ReaderActions',
290
+ Template: /*html*/`<button class="pspe-btn pspe-btn-sm" title="Duplicate this prompt" onclick="_Pict.views['{~D:Record.ViewHash~}'].duplicatePrompt()">Duplicate</button><button class="pspe-btn pspe-btn-sm pspe-btn-primary" onclick="_Pict.views['{~D:Record.ViewHash~}'].editActivePrompt()">Edit</button>`
291
+ },
266
292
  {
267
293
  Hash: 'PromptEditor-PromptEditorPanel',
268
294
  Template: /*html*/`
@@ -273,6 +299,7 @@ const _DefaultConfiguration =
273
299
  <select class="pspe-select" onchange="_Pict.views['{~D:Record.ViewHash~}'].setPromptType(this.value)">
274
300
  {~TS:PromptEditor-TypeOption:Record.TypeOptions~}
275
301
  </select>
302
+ {~TS:PromptEditor-ReadToggle:Record.ReadToggleSlot~}
276
303
  {~TS:PromptEditor-PromptActions:Record.ActionsSlot~}
277
304
  </div>
278
305
  <div class="pspe-type-desc">{~D:Record.TypeDescription~}</div>
@@ -301,6 +328,10 @@ const _DefaultConfiguration =
301
328
  { Hash: 'PromptEditor-PreviewRendered', Template: /*html*/`<div class="pspe-viewer pspe-md">{~D:Record.MarkdownHtml~}</div>` },
302
329
  { Hash: 'PromptEditor-PreviewRaw', Template: /*html*/`<pre class="pspe-viewer pspe-preview-raw">{~D:Record.MarkdownEscaped~}</pre>` },
303
330
  { Hash: 'PromptEditor-TypeOption', Template: /*html*/`<option value="{~D:Record.Value~}" {~D:Record.SelectedAttr~}>{~D:Record.Label~}</option>` },
331
+ {
332
+ Hash: 'PromptEditor-ReadToggle',
333
+ Template: /*html*/`<button class="pspe-btn pspe-btn-sm" title="Back to reading view" onclick="_Pict.views['{~D:Record.ViewHash~}'].readActivePrompt()">Done</button>`
334
+ },
304
335
  {
305
336
  Hash: 'PromptEditor-PromptActions',
306
337
  Template: /*html*/`<button class="pspe-btn pspe-btn-sm" title="Duplicate this prompt" onclick="_Pict.views['{~D:Record.ViewHash~}'].duplicatePrompt()">Duplicate</button><button class="pspe-btn pspe-btn-sm pspe-btn-danger" onclick="_Pict.views['{~D:Record.ViewHash~}'].deletePrompt()">Delete</button>`
@@ -496,7 +527,11 @@ class PictViewPromptEditor extends libPictView
496
527
  GenerateCount: this.options.GenerateDefaultCount,
497
528
  PreviewSegments: {},
498
529
  Preview: null,
499
- PreviewMode: 'rendered'
530
+ PreviewMode: 'rendered',
531
+ // Browsing a prompt shows it read-only (the assembled markdown, no
532
+ // segment boxes); 'edit' swaps in the segment editor. Selecting a
533
+ // prompt lands on 'read'; creating/duplicating/previewing enters 'edit'.
534
+ PromptMode: 'read'
500
535
  };
501
536
  this._state = {};
502
537
  this._richEditorViewHash = null;
@@ -568,7 +603,7 @@ class PictViewPromptEditor extends libPictView
568
603
  {
569
604
  let tmpPickerProvider = this.pict.providers['Pict-Section-Picker'];
570
605
  if (!tmpPickerProvider || typeof document === 'undefined') { return; }
571
- if (this._ui.Tab !== 'prompts' || this.options.ReadOnly) { return; }
606
+ if (this._ui.Tab !== 'prompts' || this.options.ReadOnly || this._ui.PromptMode === 'read') { return; }
572
607
  let tmpPrompt = this._activePrompt();
573
608
  if (!tmpPrompt) { return; }
574
609
  if (!this.pict.AppData.PromptEditorInsertPick) { this.pict.AppData.PromptEditorInsertPick = {}; }
@@ -732,6 +767,17 @@ class PictViewPromptEditor extends libPictView
732
767
  this.render();
733
768
  }
734
769
 
770
+ /* Replace the selectable prompt-type set (the cascade behind the type dropdown) and repaint. The
771
+ type list is cached as this._types at construction; a host that updates its shape library
772
+ mid-session calls this so the dropdown reflects the new set without a full page reload. */
773
+ setPromptTypes(pTypes)
774
+ {
775
+ this.options.PromptTypes = pTypes || null;
776
+ this._types = libTypes.resolvePromptTypes(this.options.PromptTypes);
777
+ this._shape();
778
+ this.render();
779
+ }
780
+
735
781
  setDataProvider(pProvider)
736
782
  {
737
783
  this._provider = pProvider || null;
@@ -855,6 +901,12 @@ class PictViewPromptEditor extends libPictView
855
901
  this._state = tmpState;
856
902
  }
857
903
 
904
+ // A prompt is browsed read-only (the assembled markdown) unless the caller
905
+ // flipped it into 'edit'. A globally ReadOnly section keeps its own preview
906
+ // path (the pReadOnly branch of _shapePromptEditor), so this only governs the
907
+ // editable library's browse-vs-edit swap.
908
+ _isPromptReadMode() { return !this.options.ReadOnly && this._ui.PromptMode !== 'edit'; }
909
+
858
910
  _shapePromptsPane(pReadOnly)
859
911
  {
860
912
  let tmpActive = this._activePrompt();
@@ -871,14 +923,36 @@ class PictViewPromptEditor extends libPictView
871
923
  OnClass: (tmpActive && tmpActive.Key === pPrompt.Key) ? 'pspe-rail-item-on' : ''
872
924
  })),
873
925
  EmptySlot: this._loaded.Prompts.length ? [] : [{ Text: 'No prompts yet.' }],
926
+ ReaderSlot: [],
874
927
  EditorSlot: [],
875
928
  NoSelectionSlot: []
876
929
  };
877
- if (tmpActive) { tmpPane.EditorSlot = [this._shapePromptEditor(tmpActive, pReadOnly)]; }
930
+ if (tmpActive && this._isPromptReadMode()) { tmpPane.ReaderSlot = [this._shapePromptReader(tmpActive)]; }
931
+ else if (tmpActive) { tmpPane.EditorSlot = [this._shapePromptEditor(tmpActive, pReadOnly)]; }
878
932
  else { tmpPane.NoSelectionSlot = [{ Text: pReadOnly ? 'Nothing to show.' : 'Create a prompt to start crafting.' }]; }
879
933
  return tmpPane;
880
934
  }
881
935
 
936
+ // The read model: the whole prompt compiled to one markdown document (the
937
+ // same source the compiler versions and generation rolls), rendered as
938
+ // content with a compact header carrying the type and browse actions.
939
+ _shapePromptReader(pPrompt)
940
+ {
941
+ let tmpType = libTypes.getPromptType(this._types, pPrompt.TypeKey);
942
+ let tmpSource = libCompiler.assembleSource(pPrompt, tmpType,
943
+ {
944
+ IncludeTitleHeading: this.options.IncludeTitleHeading,
945
+ SegmentHeadingLevel: this.options.SegmentHeadingLevel
946
+ });
947
+ return (
948
+ {
949
+ ViewHash: this.Hash,
950
+ TypeName: tmpType.Name,
951
+ ActionsSlot: this.options.ReadOnly ? [] : [{ ViewHash: this.Hash }],
952
+ MarkdownHtml: this._renderMarkdown(tmpSource)
953
+ });
954
+ }
955
+
882
956
  _shapePromptEditor(pPrompt, pReadOnly)
883
957
  {
884
958
  let tmpType = libTypes.getPromptType(this._types, pPrompt.TypeKey);
@@ -942,6 +1016,7 @@ class PictViewPromptEditor extends libPictView
942
1016
  Label: pTypeOption.Name,
943
1017
  SelectedAttr: (pTypeOption.Key === pPrompt.TypeKey) ? 'selected' : ''
944
1018
  })),
1019
+ ReadToggleSlot: pReadOnly ? [] : [{ ViewHash: this.Hash }],
945
1020
  ActionsSlot: pReadOnly ? [] : [{ ViewHash: this.Hash }],
946
1021
  OptionsSlot: pReadOnly ? [] :
947
1022
  [{
@@ -1058,6 +1133,24 @@ class PictViewPromptEditor extends libPictView
1058
1133
  {
1059
1134
  if (this._ui.ActivePromptKey !== pKey) { this._ui.Preview = null; }
1060
1135
  this._ui.ActivePromptKey = pKey;
1136
+ // Picking a prompt in the rail is browsing: land on the read view.
1137
+ this._ui.PromptMode = 'read';
1138
+ this._reshape();
1139
+ }
1140
+
1141
+ // The reader's Edit button; swap the segment editor in for the active prompt.
1142
+ editActivePrompt()
1143
+ {
1144
+ if (this.options.ReadOnly) { return; }
1145
+ this._ui.PromptMode = 'edit';
1146
+ this._reshape();
1147
+ }
1148
+
1149
+ // The editor's Done button; back to the read view, dropping any preview roll.
1150
+ readActivePrompt()
1151
+ {
1152
+ this._ui.PromptMode = 'read';
1153
+ this._ui.Preview = null;
1061
1154
  this._reshape();
1062
1155
  }
1063
1156
  selectWordList(pKey) { this._ui.ActiveWordListKey = pKey; this._reshape(); }
@@ -1071,6 +1164,8 @@ class PictViewPromptEditor extends libPictView
1071
1164
  .then((pPrompt) =>
1072
1165
  {
1073
1166
  this._ui.ActivePromptKey = pPrompt.Key;
1167
+ // A fresh prompt opens ready to write in, not in the read view.
1168
+ this._ui.PromptMode = 'edit';
1074
1169
  this._fire('onPromptSaved', pPrompt);
1075
1170
  return this.load();
1076
1171
  })
@@ -1123,6 +1218,8 @@ class PictViewPromptEditor extends libPictView
1123
1218
  .then((pCopy) =>
1124
1219
  {
1125
1220
  this._ui.ActivePromptKey = pCopy.Key;
1221
+ // A copy is made to be changed; open it in the editor.
1222
+ this._ui.PromptMode = 'edit';
1126
1223
  this._fire('onPromptSaved', pCopy);
1127
1224
  return this.load();
1128
1225
  })
@@ -1342,6 +1439,8 @@ class PictViewPromptEditor extends libPictView
1342
1439
  let tmpPrompt = this._activePrompt();
1343
1440
  if (!tmpPrompt) { return; }
1344
1441
  let tmpType = libTypes.getPromptType(this._types, tmpPrompt.TypeKey);
1442
+ // The preview roll lives under the segment editor; rolling implies editing.
1443
+ this._ui.PromptMode = 'edit';
1345
1444
  this._ui.Preview = { PromptKey: tmpPrompt.Key, Markdown: this._generateOnce(tmpPrompt, tmpType) };
1346
1445
  this._reshape();
1347
1446
  }