@inshapardaz/likhari-react 0.1.18-dev.138 → 0.1.18-dev.142

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.
@@ -1 +1 @@
1
- {"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAY1D,OAAO,KAAK,EAA8B,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEjF,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,EAAwB,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAKzH,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAMjE,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAYhF,OAAO,EAAgC,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAMnE,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,YAAY,GAAG,KAAK,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC;;;;;;;;;;;;;;;OAeG;IACH,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,uGAAuG;IACvG,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3E,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IACrC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClD,iBAAiB,IAAI,OAAO,CAAC;IAC7B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAQD,eAAO,MAAM,UAAU,uGAoXrB,CAAC"}
1
+ {"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAY1D,OAAO,KAAK,EAA8B,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEjF,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,EAAwB,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAKzH,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAOjE,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAYhF,OAAO,EAAgC,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAMnE,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,YAAY,GAAG,KAAK,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC;;;;;;;;;;;;;;;OAeG;IACH,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,uGAAuG;IACvG,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3E,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IACrC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClD,iBAAiB,IAAI,OAAO,CAAC;IAC7B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAQD,eAAO,MAAM,UAAU,uGAqXrB,CAAC"}
@@ -24,6 +24,7 @@ import { PageBreakPlugin } from './plugins/PageBreakPlugin.js';
24
24
  import { LayoutPlugin } from './plugins/LayoutPlugin.js';
25
25
  import { FootnotePlugin } from './plugins/FootnotePlugin.js';
26
26
  import { PoetryPlugin } from './plugins/PoetryPlugin.js';
27
+ import { PoetryResizer } from './blocks/PoetryResizer.js';
27
28
  import { DraftRestore } from './components/DraftRestore.js';
28
29
  import { LeaveDialog } from './components/LeaveDialog.js';
29
30
  import { clearDraft, createDraftId, hasDraftContent, pruneDrafts, writeDraft, } from './persistence/draftStorage.js';
@@ -280,7 +281,7 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialCo
280
281
  const portalTargetSelector = `#${CSS.escape(portalTargetId)}`;
281
282
  return (_jsx(EditorThemeProvider, { theme: theme, colorScheme: colorScheme, accentColor: accentColor, scopeElementId: portalTargetId, children: _jsxs("div", { className: "likhari-root", dir: dir, ref: rootElementRef, "data-document-id": documentId, style: { height: typeof height === 'number' ? `${height}px` : height }, children: [_jsx("div", { id: portalTargetId, className: "likhari-portal-target" }), _jsx(PortalTargetContext.Provider, { value: portalTargetSelector, children: _jsxs(UiStringsContext.Provider, { value: strings, children: [_jsx(ImageOptionsContext.Provider, { value: imageOptions, children: _jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Toolbar, { config: config, onSave: handleSave, isDirty: isDirty, showSave: showSave, fontOptions: fontOptions, direction: dir, locale: locale, drafts: autosave
282
283
  ? { currentId: draftId, maxBytes: autosaveMaxBytes, adoptOnRestore: !documentId, onRestored: handleDraftRestored }
283
- : undefined }), documentId && (_jsx(DraftRestore, { draftId: documentId, mode: restoreDraft, initialJson: initialContentJsonRef.current, locale: locale, onRestored: handleDraftRestored })), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, "aria-label": strings.editor.contentLabel }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), config.blocks.pageBreak && _jsx(PageBreakPlugin, {}), config.columns && _jsx(LayoutPlugin, {}), config.footnotes && _jsx(FootnotePlugin, {}), config.poetry.enabled && _jsx(PoetryPlugin, {}), config.tables && _jsx(TablePlugin, { hasCellMerge: true, hasTabHandler: true }), config.blocks.horizontalRule && _jsx(HorizontalRulePlugin, {}), _jsx(EditorInstancePlugin, { instanceRef: editorInstanceRef }), _jsx(OnChangePlugin, { onChange: handleChange })] }) }), _jsx(LeaveDialog, { opened: leavePrompt !== null, canSave: Boolean(onSave), canSaveDraft: autosave || navigationGuard === 'save-draft', draftFailed: leavePrompt?.draftFailed ?? false, onSave: () => {
284
+ : undefined }), documentId && (_jsx(DraftRestore, { draftId: documentId, mode: restoreDraft, initialJson: initialContentJsonRef.current, locale: locale, onRestored: handleDraftRestored })), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, "aria-label": strings.editor.contentLabel }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), config.blocks.pageBreak && _jsx(PageBreakPlugin, {}), config.columns && _jsx(LayoutPlugin, {}), config.footnotes && _jsx(FootnotePlugin, {}), config.poetry.enabled && _jsx(PoetryPlugin, {}), config.poetry.enabled && _jsx(PoetryResizer, {}), config.tables && _jsx(TablePlugin, { hasCellMerge: true, hasTabHandler: true }), config.blocks.horizontalRule && _jsx(HorizontalRulePlugin, {}), _jsx(EditorInstancePlugin, { instanceRef: editorInstanceRef }), _jsx(OnChangePlugin, { onChange: handleChange })] }) }), _jsx(LeaveDialog, { opened: leavePrompt !== null, canSave: Boolean(onSave), canSaveDraft: autosave || navigationGuard === 'save-draft', draftFailed: leavePrompt?.draftFailed ?? false, onSave: () => {
284
285
  handleSave();
285
286
  settleLeave(true);
286
287
  }, onSaveDraft: () => {
@@ -4,6 +4,7 @@ export type PoetryAlign = 'justify' | 'left' | 'right' | 'start';
4
4
  export type SerializedPoetryBlockNode = Spread<{
5
5
  layout: PoetryLayout;
6
6
  align: PoetryAlign;
7
+ width?: number;
7
8
  }, SerializedElementNode>;
8
9
  /**
9
10
  * A couplet (two-line verse unit), the one extensible primitive requirements
@@ -18,11 +19,16 @@ export type SerializedPoetryBlockNode = Spread<{
18
19
  export declare class PoetryBlockNode extends ElementNode {
19
20
  __layout: PoetryLayout;
20
21
  __align: PoetryAlign;
21
- constructor(layout?: PoetryLayout, align?: PoetryAlign, key?: NodeKey);
22
+ /** User-chosen width in px (drag-resized), overriding editor.css's default
23
+ * max-width: 70%. Undefined until the user resizes it. */
24
+ __width?: number;
25
+ constructor(layout?: PoetryLayout, align?: PoetryAlign, width?: number, key?: NodeKey);
22
26
  static getType(): string;
23
27
  static clone(node: PoetryBlockNode): PoetryBlockNode;
24
28
  getLayout(): PoetryLayout;
25
29
  getAlign(): PoetryAlign;
30
+ getWidth(): number | undefined;
31
+ setWidth(width: number | undefined): this;
26
32
  /** Attribute-only — restructuring children for a layout change is
27
33
  * poetryActions.ts's $setPoetryLayout, not a node method, since it needs
28
34
  * $-context tree mutations beyond this node's own state. */
@@ -37,6 +43,6 @@ export declare class PoetryBlockNode extends ElementNode {
37
43
  canBeEmpty(): false;
38
44
  isShadowRoot(): boolean;
39
45
  }
40
- export declare function $createPoetryBlockNode(layout?: PoetryLayout, align?: PoetryAlign): PoetryBlockNode;
46
+ export declare function $createPoetryBlockNode(layout?: PoetryLayout, align?: PoetryAlign, width?: number): PoetryBlockNode;
41
47
  export declare function $isPoetryBlockNode(node: LexicalNode | null | undefined): node is PoetryBlockNode;
42
48
  //# sourceMappingURL=PoetryNode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PoetryNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,CAAC;AACnD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAgBjE,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,EAAE,qBAAqB,CAAC,CAAC;AAEpH;;;;;;;;;GASG;AACH,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;gBAET,MAAM,GAAE,YAAuB,EAAE,KAAK,GAAE,WAAuB,EAAE,GAAG,CAAC,EAAE,OAAO;IAM1F,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe;IAIpD,SAAS,IAAI,YAAY;IAIzB,QAAQ,IAAI,WAAW;IAIvB;;gEAE4D;IAC5D,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAM9C,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAMlC,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,yBAAyB,GAAG,eAAe;IAI7E,UAAU,IAAI,yBAAyB;IAIvC,MAAM,CAAC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAa3C,SAAS,IAAI,eAAe;IAQ5B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAY5C,SAAS,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO;IAYrF,UAAU,IAAI,KAAK;IAInB,YAAY,IAAI,OAAO;CAGxB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,YAAuB,EAAE,KAAK,GAAE,WAAuB,GAAG,eAAe,CAEvH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,eAAe,CAEhG"}
1
+ {"version":3,"file":"PoetryNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,CAAC;AACnD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAwBjE,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,qBAAqB,CAAC,CAAC;AAEpI;;;;;;;;;GASG;AACH,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB;8DAC0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;gBAEL,MAAM,GAAE,YAAuB,EAAE,KAAK,GAAE,WAAuB,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO;IAO1G,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe;IAIpD,SAAS,IAAI,YAAY;IAIzB,QAAQ,IAAI,WAAW;IAIvB,QAAQ,IAAI,MAAM,GAAG,SAAS;IAI9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAMzC;;gEAE4D;IAC5D,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAM9C,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAMlC,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,yBAAyB,GAAG,eAAe;IAI7E,UAAU,IAAI,yBAAyB;IAYvC,MAAM,CAAC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAe3C,SAAS,IAAI,eAAe;IAW5B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAa5C,SAAS,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO;IAerF,UAAU,IAAI,KAAK;IAInB,YAAY,IAAI,OAAO;CAGxB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,YAAuB,EAAE,KAAK,GAAE,WAAuB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,eAAe,CAEvI;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,eAAe,CAEhG"}
@@ -12,6 +12,15 @@ function applyAlignStyle(element, align) {
12
12
  element.style.textAlign = align;
13
13
  element.style.textAlignLast = align === 'justify' ? 'justify' : '';
14
14
  }
15
+ /** A user-dragged width overrides editor.css's default max-width: 70% —
16
+ * clearing the inline style (rather than setting it to that same 70%)
17
+ * lets the CSS default keep tracking the canvas if it's ever resized. */
18
+ function applyWidthStyle(element, width) {
19
+ if (width === undefined)
20
+ element.style.removeProperty('max-width');
21
+ else
22
+ element.style.maxWidth = `${width}px`;
23
+ }
15
24
  /**
16
25
  * A couplet (two-line verse unit), the one extensible primitive requirements
17
26
  * doc §4.11 recommends in place of four fixed templates. `layout` picks
@@ -23,16 +32,17 @@ function applyAlignStyle(element, align) {
23
32
  * between layouts doesn't lose selection/undo coherence.
24
33
  */
25
34
  export class PoetryBlockNode extends ElementNode {
26
- constructor(layout = 'single', align = 'justify', key) {
35
+ constructor(layout = 'single', align = 'justify', width, key) {
27
36
  super(key);
28
37
  this.__layout = layout;
29
38
  this.__align = align;
39
+ this.__width = width;
30
40
  }
31
41
  static getType() {
32
42
  return 'poetry-couplet';
33
43
  }
34
44
  static clone(node) {
35
- return new PoetryBlockNode(node.__layout, node.__align, node.__key);
45
+ return new PoetryBlockNode(node.__layout, node.__align, node.__width, node.__key);
36
46
  }
37
47
  getLayout() {
38
48
  return this.getLatest().__layout;
@@ -40,6 +50,14 @@ export class PoetryBlockNode extends ElementNode {
40
50
  getAlign() {
41
51
  return this.getLatest().__align;
42
52
  }
53
+ getWidth() {
54
+ return this.getLatest().__width;
55
+ }
56
+ setWidth(width) {
57
+ const writable = this.getWritable();
58
+ writable.__width = width;
59
+ return writable;
60
+ }
43
61
  /** Attribute-only — restructuring children for a layout change is
44
62
  * poetryActions.ts's $setPoetryLayout, not a node method, since it needs
45
63
  * $-context tree mutations beyond this node's own state. */
@@ -54,10 +72,18 @@ export class PoetryBlockNode extends ElementNode {
54
72
  return writable;
55
73
  }
56
74
  static importJSON(serializedNode) {
57
- return $createPoetryBlockNode(serializedNode.layout, serializedNode.align);
75
+ return $createPoetryBlockNode(serializedNode.layout, serializedNode.align, serializedNode.width);
58
76
  }
59
77
  exportJSON() {
60
- return { ...super.exportJSON(), type: 'poetry-couplet', version: 1, layout: this.getLayout(), align: this.getAlign() };
78
+ const width = this.getWidth();
79
+ return {
80
+ ...super.exportJSON(),
81
+ type: 'poetry-couplet',
82
+ version: 1,
83
+ layout: this.getLayout(),
84
+ align: this.getAlign(),
85
+ ...(width !== undefined ? { width } : {}),
86
+ };
61
87
  }
62
88
  static importDOM() {
63
89
  return {
@@ -68,7 +94,9 @@ export class PoetryBlockNode extends ElementNode {
68
94
  const layout = VALID_LAYOUTS.has(rawLayout) ? rawLayout : 'single';
69
95
  const rawAlign = domNode.getAttribute('data-likhari-poetry-align') ?? 'justify';
70
96
  const align = VALID_ALIGNS.has(rawAlign) ? rawAlign : 'justify';
71
- return { conversion: () => ({ node: $createPoetryBlockNode(layout, align) }), priority: 2 };
97
+ const rawWidth = Number(domNode.getAttribute('data-likhari-poetry-width'));
98
+ const width = Number.isFinite(rawWidth) && rawWidth > 0 ? rawWidth : undefined;
99
+ return { conversion: () => ({ node: $createPoetryBlockNode(layout, align, width) }), priority: 2 };
72
100
  },
73
101
  };
74
102
  }
@@ -76,7 +104,11 @@ export class PoetryBlockNode extends ElementNode {
76
104
  const element = document.createElement('div');
77
105
  element.setAttribute('data-likhari-poetry-layout', this.getLayout());
78
106
  element.setAttribute('data-likhari-poetry-align', this.getAlign());
107
+ const width = this.getWidth();
108
+ if (width !== undefined)
109
+ element.setAttribute('data-likhari-poetry-width', String(width));
79
110
  applyAlignStyle(element, this.getAlign());
111
+ applyWidthStyle(element, width);
80
112
  return { element };
81
113
  }
82
114
  createDOM(config) {
@@ -84,6 +116,7 @@ export class PoetryBlockNode extends ElementNode {
84
116
  const base = config.theme.poetry ?? 'likhari-poetry';
85
117
  addClassNamesToElement(element, base, `${base}--${this.__layout}`);
86
118
  applyAlignStyle(element, this.__align);
119
+ applyWidthStyle(element, this.__width);
87
120
  return element;
88
121
  }
89
122
  // Only ever adds/removes the layout modifier class, never touches the
@@ -99,6 +132,9 @@ export class PoetryBlockNode extends ElementNode {
99
132
  if (prevNode.__align !== this.__align) {
100
133
  applyAlignStyle(dom, this.__align);
101
134
  }
135
+ if (prevNode.__width !== this.__width) {
136
+ applyWidthStyle(dom, this.__width);
137
+ }
102
138
  return false;
103
139
  }
104
140
  canBeEmpty() {
@@ -108,8 +144,8 @@ export class PoetryBlockNode extends ElementNode {
108
144
  return true;
109
145
  }
110
146
  }
111
- export function $createPoetryBlockNode(layout = 'single', align = 'justify') {
112
- return $applyNodeReplacement(new PoetryBlockNode(layout, align));
147
+ export function $createPoetryBlockNode(layout = 'single', align = 'justify', width) {
148
+ return $applyNodeReplacement(new PoetryBlockNode(layout, align, width));
113
149
  }
114
150
  export function $isPoetryBlockNode(node) {
115
151
  return node instanceof PoetryBlockNode;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * A floating drag handle over the currently-active poetry couplet's
3
+ * inline-end edge, letting the user resize how wide the block reads on the
4
+ * page — "size it according to the length of the couplet" — rather than
5
+ * being stuck with editor.css's default max-width: 70%. Rendered as a
6
+ * portal into the editor's own portal-target element, never as a child of
7
+ * the couplet's own DOM, so it can't interfere with Lexical's
8
+ * reconciliation of the couplet's real (editable) children.
9
+ */
10
+ export declare function PoetryResizer(): import("react").JSX.Element | null;
11
+ //# sourceMappingURL=PoetryResizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PoetryResizer.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryResizer.tsx"],"names":[],"mappings":"AAuBA;;;;;;;;GAQG;AACH,wBAAgB,aAAa,uCAqF5B"}
@@ -0,0 +1,94 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
5
+ import { $getNodeByKey } from 'lexical';
6
+ import { usePortalTarget } from '../PortalTargetContext.js';
7
+ import { $getPoetryBlockFromSelection } from './poetryActions.js';
8
+ import { $isPoetryBlockNode } from './PoetryNode.js';
9
+ const MIN_WIDTH_PX = 160;
10
+ function measure(el) {
11
+ const box = el.getBoundingClientRect();
12
+ return { top: box.top, left: box.left, width: box.width, height: box.height, rtl: getComputedStyle(el).direction === 'rtl' };
13
+ }
14
+ /**
15
+ * A floating drag handle over the currently-active poetry couplet's
16
+ * inline-end edge, letting the user resize how wide the block reads on the
17
+ * page — "size it according to the length of the couplet" — rather than
18
+ * being stuck with editor.css's default max-width: 70%. Rendered as a
19
+ * portal into the editor's own portal-target element, never as a child of
20
+ * the couplet's own DOM, so it can't interfere with Lexical's
21
+ * reconciliation of the couplet's real (editable) children.
22
+ */
23
+ export function PoetryResizer() {
24
+ const [editor] = useLexicalComposerContext();
25
+ const portalSelector = usePortalTarget();
26
+ const [activeKey, setActiveKey] = useState(null);
27
+ const [box, setBox] = useState(null);
28
+ const dragStart = useRef(null);
29
+ useEffect(() => {
30
+ const recompute = () => {
31
+ if (dragStart.current)
32
+ return; // the pointermove handler owns `box` mid-drag
33
+ editor.getEditorState().read(() => {
34
+ const couplet = $getPoetryBlockFromSelection();
35
+ const el = couplet ? editor.getElementByKey(couplet.getKey()) : null;
36
+ if (!couplet || !el) {
37
+ setActiveKey(null);
38
+ setBox(null);
39
+ return;
40
+ }
41
+ setActiveKey(couplet.getKey());
42
+ setBox(measure(el));
43
+ });
44
+ };
45
+ recompute();
46
+ const unregister = editor.registerUpdateListener(recompute);
47
+ window.addEventListener('resize', recompute);
48
+ window.addEventListener('scroll', recompute, true);
49
+ return () => {
50
+ unregister();
51
+ window.removeEventListener('resize', recompute);
52
+ window.removeEventListener('scroll', recompute, true);
53
+ };
54
+ }, [editor]);
55
+ if (!box || !activeKey)
56
+ return null;
57
+ const onPointerDown = (event) => {
58
+ event.preventDefault();
59
+ event.currentTarget.setPointerCapture(event.pointerId);
60
+ dragStart.current = { x: event.clientX, width: box.width, rtl: box.rtl };
61
+ };
62
+ const onPointerMove = (event) => {
63
+ const start = dragStart.current;
64
+ const el = editor.getElementByKey(activeKey);
65
+ if (!start || !el)
66
+ return;
67
+ const delta = event.clientX - start.x;
68
+ const signedDelta = start.rtl ? -delta : delta;
69
+ const canvasMax = editor.getRootElement()?.clientWidth ?? start.width + signedDelta;
70
+ const width = Math.round(Math.min(Math.max(start.width + signedDelta, MIN_WIDTH_PX), canvasMax));
71
+ // Live visual feedback: the couplet is centered (margin: auto), so
72
+ // resizing it moves both edges — re-measure after mutating rather than
73
+ // computing the new position from the drag delta alone.
74
+ el.style.maxWidth = `${width}px`;
75
+ setBox(measure(el));
76
+ };
77
+ const onPointerUp = () => {
78
+ const start = dragStart.current;
79
+ dragStart.current = null;
80
+ const el = editor.getElementByKey(activeKey);
81
+ const width = el ? Math.round(el.getBoundingClientRect().width) : null;
82
+ if (start && width !== null) {
83
+ editor.update(() => {
84
+ const node = $getNodeByKey(activeKey);
85
+ if ($isPoetryBlockNode(node))
86
+ node.setWidth(width);
87
+ });
88
+ }
89
+ };
90
+ const handleX = box.rtl ? box.left : box.left + box.width;
91
+ const handle = (_jsx("div", { className: "likhari-poetry-resize-handle", style: { position: 'fixed', top: box.top, left: handleX, height: box.height }, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, role: "separator", "aria-orientation": "vertical" }));
92
+ const portalRoot = portalSelector ? document.querySelector(portalSelector) : null;
93
+ return portalRoot ? createPortal(handle, portalRoot) : handle;
94
+ }
@@ -406,18 +406,55 @@
406
406
 
407
407
  .likhari-poetry--two-column .likhari-layout-container {
408
408
  margin: 0;
409
- gap: 16px;
409
+ /* No grid gap — the divider below sits exactly on the track boundary, so
410
+ spacing instead comes from matching padding on each side of it, which
411
+ keeps the gutter visually even on both sides of the line. */
412
+ gap: 0;
410
413
  }
411
414
 
412
415
  .likhari-poetry--two-column .likhari-layout-item {
413
416
  text-align: inherit;
414
417
  }
415
418
 
419
+ .likhari-poetry--two-column .likhari-layout-item:first-child {
420
+ padding-inline-end: 20px;
421
+ }
422
+
416
423
  /* A visible divider between misra columns, same dashed language as the
417
424
  couplet's own border — matches a table's internal cell borders. */
418
425
  .likhari-poetry--two-column .likhari-layout-item:not(:first-child) {
419
426
  border-inline-start: 1px dashed var(--editor-line-strong);
420
- padding-inline-start: 16px;
427
+ padding-inline-start: 20px;
428
+ }
429
+
430
+ /* PoetryResizer.tsx's drag handle — portaled to a fixed position over the
431
+ active couplet's inline-end edge, so top/left are set inline per drag. */
432
+ .likhari-poetry-resize-handle {
433
+ position: fixed;
434
+ width: 10px;
435
+ /* Physical, not logical: PoetryResizer.tsx already computes `left` as the
436
+ couplet's actual edge in viewport coordinates for either direction, so
437
+ centering the handle on it must stay physical too. */
438
+ margin-left: -5px;
439
+ cursor: ew-resize;
440
+ touch-action: none;
441
+ z-index: 20;
442
+ }
443
+
444
+ .likhari-poetry-resize-handle::before {
445
+ content: '';
446
+ display: block;
447
+ width: 3px;
448
+ height: 100%;
449
+ margin-inline: auto;
450
+ border-radius: 2px;
451
+ background: var(--editor-accent);
452
+ opacity: 0;
453
+ transition: opacity 0.1s ease;
454
+ }
455
+
456
+ .likhari-poetry-resize-handle:hover::before {
457
+ opacity: 0.6;
421
458
  }
422
459
 
423
460
  .likhari-table {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inshapardaz/likhari-react",
3
- "version": "0.1.18-dev.138",
3
+ "version": "0.1.18-dev.142",
4
4
  "description": "React implementation of the Likhari editor, built on @lexical/react.",
5
5
  "license": "MIT",
6
6
  "repository": {