@octane-xplat/richtext 0.9.0 → 0.11.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.
@@ -1,7 +1,7 @@
1
- import { defineUniversalComponent, hookSlots, registerElement, universalPlan, universalValue, useCallback, useEffect, useRef } from "@nativescript-community/octane";
1
+ import { defineUniversalComponent, hookSlots, registerElement, universalPlan, universalValue, useCallback, useEffect, useImperativeHandle, useRef } from "@nativescript-community/octane";
2
2
  import { View } from "@nativescript/core";
3
3
  //#region src/RichTextEditor.android.tsrx
4
- var _hs$ = /* @__PURE__ */ hookSlots(10);
4
+ var _hs$ = /* @__PURE__ */ hookSlots(11);
5
5
  var _h$0 = /* @__PURE__ */ Symbol(_hs$);
6
6
  var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
7
7
  var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
@@ -12,6 +12,7 @@ var _h$6 = /* @__PURE__ */ Symbol(_hs$ + 6);
12
12
  var _h$7 = /* @__PURE__ */ Symbol(_hs$ + 7);
13
13
  var _h$8 = /* @__PURE__ */ Symbol(_hs$ + 8);
14
14
  var _h$9 = /* @__PURE__ */ Symbol(_hs$ + 9);
15
+ var _h$10 = /* @__PURE__ */ Symbol(_hs$ + 10);
15
16
  var __octaneUniversalPlan0 = universalPlan("nativescript", {
16
17
  "kind": "host",
17
18
  "type": "xplatrichtext",
@@ -87,9 +88,10 @@ var RichTextEditor = defineUniversalComponent("nativescript", function RichTextE
87
88
  const applyingValue = useRef(false, _h$2);
88
89
  const keyListener = useRef(null, _h$3);
89
90
  const emitTimer = useRef(null, _h$4);
91
+ useImperativeHandle(props.ref, () => handle(editor()), [], _h$5);
90
92
  const bindHost = useCallback((v) => {
91
93
  host.current = v;
92
- }, [], _h$5);
94
+ }, [], _h$6);
93
95
  const editor = () => host.current?.android;
94
96
  const setEditable = (next) => {
95
97
  const e = editor();
@@ -154,6 +156,45 @@ var RichTextEditor = defineUniversalComponent("nativescript", function RichTextE
154
156
  },
155
157
  undo: () => e.undo(),
156
158
  redo: () => e.redo(),
159
+ split: () => {
160
+ const selStart = e.getSelectionStart();
161
+ const selEnd = e.getSelectionEnd();
162
+ if (selStart < 0 || selEnd < 0) return false;
163
+ const start = Math.min(selStart, selEnd);
164
+ const end = Math.max(selStart, selEnd);
165
+ const text = e.getText();
166
+ if (end > String(text).length) return false;
167
+ if (end > start) text.delete(start, end);
168
+ text.insert(start, "\n");
169
+ e.setSelection(start + 1);
170
+ emitChange();
171
+ return true;
172
+ },
173
+ join: () => {
174
+ const start = e.getSelectionStart();
175
+ if (start <= 0 || e.getSelectionEnd() !== start) return false;
176
+ const text = e.getText();
177
+ const s = String(text);
178
+ if (start > s.length || s.charAt(start - 1) !== "\n") return false;
179
+ text.delete(start - 1, start);
180
+ e.setSelection(start - 1);
181
+ emitChange();
182
+ return true;
183
+ },
184
+ indent: () => {
185
+ if (!e.isIndentAvailable()) return false;
186
+ e.indent();
187
+ emitChange();
188
+ return true;
189
+ },
190
+ outdent: () => {
191
+ if (!e.isOutdentAvailable()) return false;
192
+ e.outdent();
193
+ emitChange();
194
+ return true;
195
+ },
196
+ canIndent: () => Boolean(e.isIndentAvailable()),
197
+ canOutdent: () => Boolean(e.isOutdentAvailable()),
157
198
  focus: () => {
158
199
  e.requestFocus();
159
200
  showKeyboard(e);
@@ -191,9 +232,8 @@ var RichTextEditor = defineUniversalComponent("nativescript", function RichTextE
191
232
  showKeyboard(e);
192
233
  }
193
234
  if (props.android) Object.assign(e, props.android);
194
- props.bind?.(handle(e));
195
235
  props.onReady?.();
196
- }, [], _h$6);
236
+ }, [], _h$7);
197
237
  useEffect(() => {
198
238
  const e = editor();
199
239
  if (!e || props.value === void 0) return;
@@ -204,14 +244,14 @@ var RichTextEditor = defineUniversalComponent("nativescript", function RichTextE
204
244
  } finally {
205
245
  applyingValue.current = false;
206
246
  }
207
- }, [props.value], _h$7);
247
+ }, [props.value], _h$8);
208
248
  useEffect(() => {
209
249
  setEditable(props.editable !== false);
210
- }, [props.editable], _h$8);
250
+ }, [props.editable], _h$9);
211
251
  useEffect(() => {
212
252
  const e = editor();
213
253
  if (e && props.placeholder !== void 0) e.setHint(props.placeholder);
214
- }, [props.placeholder], _h$9);
254
+ }, [props.placeholder], _h$10);
215
255
  return universalValue(__octaneUniversalPlan0, [
216
256
  bindHost,
217
257
  props.id,
@@ -1,21 +1,207 @@
1
- import { defineUniversalComponent, universalPlan, universalValue } from "@nativescript-community/octane";
1
+ import { defineUniversalComponent, hookSlots, registerElement, universalPlan, universalValue, useCallback, useEffect, useImperativeHandle, useRef } from "@nativescript-community/octane";
2
+ import { View } from "@nativescript/core";
2
3
  //#region src/RichTextEditor.ios.tsrx
4
+ var _hs$ = /* @__PURE__ */ hookSlots(11);
5
+ var _h$0 = /* @__PURE__ */ Symbol(_hs$);
6
+ var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
7
+ var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
8
+ var _h$3 = /* @__PURE__ */ Symbol(_hs$ + 3);
9
+ var _h$4 = /* @__PURE__ */ Symbol(_hs$ + 4);
10
+ var _h$5 = /* @__PURE__ */ Symbol(_hs$ + 5);
11
+ var _h$6 = /* @__PURE__ */ Symbol(_hs$ + 6);
12
+ var _h$7 = /* @__PURE__ */ Symbol(_hs$ + 7);
13
+ var _h$8 = /* @__PURE__ */ Symbol(_hs$ + 8);
14
+ var _h$9 = /* @__PURE__ */ Symbol(_hs$ + 9);
15
+ var _h$10 = /* @__PURE__ */ Symbol(_hs$ + 10);
3
16
  var __octaneUniversalPlan0 = universalPlan("nativescript", {
4
17
  "kind": "host",
5
- "type": "label",
6
- "props": { "text": "Rich text editing is not supported on iOS yet." },
18
+ "type": "xplatrichtext",
7
19
  "bindings": [
8
- ["id", 0],
9
- ["className", 1],
10
- ["style", 2]
20
+ ["ref", 0],
21
+ ["id", 1],
22
+ ["className", 2],
23
+ ["style", 3],
24
+ ["row", 4],
25
+ ["col", 5],
26
+ ["rowSpan", 6],
27
+ ["colSpan", 7],
28
+ ["dock", 8],
29
+ ["left", 9],
30
+ ["top", 10],
31
+ ["flexGrow", 11],
32
+ ["flexShrink", 12],
33
+ ["alignSelf", 13],
34
+ ["order", 14]
11
35
  ]
12
36
  });
13
- var supported = false;
37
+ var UNSUPPORTED = /* @__PURE__ */ new Set([
38
+ "taskList",
39
+ "alignLeft",
40
+ "alignCenter",
41
+ "alignRight"
42
+ ]);
43
+ var AztecEditor = class extends View {
44
+ createNativeView() {
45
+ return new XplatAztecEditorView();
46
+ }
47
+ };
48
+ registerElement("xplatrichtext", AztecEditor);
49
+ var supported = true;
14
50
  var RichTextEditor = defineUniversalComponent("nativescript", function RichTextEditor(props) {
51
+ const host = useRef(null, _h$0);
52
+ const lastEmitted = useRef(void 0, _h$1);
53
+ const applyingValue = useRef(false, _h$2);
54
+ const emitTimer = useRef(null, _h$3);
55
+ const warned = useRef(/* @__PURE__ */ new Set(), _h$4);
56
+ useImperativeHandle(props.ref, () => handle(editor()), [], _h$5);
57
+ const bindHost = useCallback((v) => {
58
+ host.current = v;
59
+ }, [], _h$6);
60
+ const editor = () => host.current?.ios;
61
+ const emitChange = () => {
62
+ if (!editor() || applyingValue.current) return;
63
+ clearTimeout(emitTimer.current);
64
+ emitTimer.current = setTimeout(() => {
65
+ const current = editor();
66
+ if (!current || applyingValue.current) return;
67
+ const html = current.getHTML();
68
+ lastEmitted.current = html;
69
+ props.onChange?.(html);
70
+ }, 150);
71
+ };
72
+ const reportUnsupported = (format) => {
73
+ if (warned.current.has(format)) return;
74
+ warned.current.add(format);
75
+ console.warn(`[richtext] apply('${format}') is not supported by the iOS Aztec surface`);
76
+ };
77
+ const handle = (e) => ({
78
+ getHTML: () => e.getHTML(),
79
+ setHTML: (html) => {
80
+ applyingValue.current = true;
81
+ try {
82
+ e.setHTML(html);
83
+ lastEmitted.current = html;
84
+ } finally {
85
+ applyingValue.current = false;
86
+ }
87
+ },
88
+ apply: (format) => {
89
+ if (format === "link") return;
90
+ if (UNSUPPORTED.has(format) || !e.applyFormat(format)) {
91
+ reportUnsupported(format);
92
+ return;
93
+ }
94
+ emitChange();
95
+ },
96
+ linkTo: (url, anchor) => {
97
+ e.linkTo(url, anchor ?? null);
98
+ emitChange();
99
+ },
100
+ removeLink: () => {
101
+ e.removeLink();
102
+ emitChange();
103
+ },
104
+ isActive: (format) => !UNSUPPORTED.has(format) && Boolean(e.isFormatActive(format)),
105
+ undo: () => e.undo(),
106
+ redo: () => e.redo(),
107
+ split: () => {
108
+ const ok = Boolean(e.split());
109
+ if (ok) emitChange();
110
+ return ok;
111
+ },
112
+ join: () => {
113
+ const ok = Boolean(e.join());
114
+ if (ok) emitChange();
115
+ return ok;
116
+ },
117
+ indent: () => {
118
+ const ok = Boolean(e.indent());
119
+ if (ok) emitChange();
120
+ return ok;
121
+ },
122
+ outdent: () => {
123
+ const ok = Boolean(e.outdent());
124
+ if (ok) emitChange();
125
+ return ok;
126
+ },
127
+ canIndent: () => Boolean(e.canIndent()),
128
+ canOutdent: () => Boolean(e.canOutdent()),
129
+ focus: () => e.focus(),
130
+ blur: () => e.blur(),
131
+ isFocused: () => e.focused(),
132
+ native: e
133
+ });
134
+ useEffect(() => {
135
+ const e = editor();
136
+ if (!e) return;
137
+ e.onTextChange = () => emitChange();
138
+ e.onSelectionChange = (start, end, active) => {
139
+ const formats = [];
140
+ const count = active?.count ?? 0;
141
+ for (let i = 0; i < count; i++) formats.push(active.objectAtIndex(i));
142
+ props.onSelectionChange?.({
143
+ start,
144
+ end,
145
+ active: formats
146
+ });
147
+ };
148
+ e.onFocus = () => props.onFocus?.();
149
+ e.onBlur = () => props.onBlur?.();
150
+ if (props.placeholder !== void 0) e.placeholder = props.placeholder;
151
+ e.editable = props.editable !== false;
152
+ if (props.value !== void 0) {
153
+ applyingValue.current = true;
154
+ try {
155
+ e.setHTML(props.value);
156
+ } finally {
157
+ applyingValue.current = false;
158
+ }
159
+ }
160
+ if (props.autofocus) e.focus();
161
+ if (props.ios) Object.assign(e, props.ios);
162
+ props.onReady?.();
163
+ return () => {
164
+ e.onTextChange = null;
165
+ e.onSelectionChange = null;
166
+ e.onFocus = null;
167
+ e.onBlur = null;
168
+ };
169
+ }, [], _h$7);
170
+ useEffect(() => {
171
+ const e = editor();
172
+ if (!e || props.value === void 0) return;
173
+ if (props.value === lastEmitted.current) return;
174
+ applyingValue.current = true;
175
+ try {
176
+ e.setHTML(props.value);
177
+ } finally {
178
+ applyingValue.current = false;
179
+ }
180
+ }, [props.value], _h$8);
181
+ useEffect(() => {
182
+ const e = editor();
183
+ if (e) e.editable = props.editable !== false;
184
+ }, [props.editable], _h$9);
185
+ useEffect(() => {
186
+ const e = editor();
187
+ if (e && props.placeholder !== void 0) e.placeholder = props.placeholder;
188
+ }, [props.placeholder], _h$10);
15
189
  return universalValue(__octaneUniversalPlan0, [
190
+ bindHost,
16
191
  props.id,
17
192
  props.className,
18
- props.style
193
+ props.style,
194
+ props.row,
195
+ props.col,
196
+ props.rowSpan,
197
+ props.colSpan,
198
+ props.dock,
199
+ props.left,
200
+ props.top,
201
+ props.flexGrow,
202
+ props.flexShrink,
203
+ props.alignSelf,
204
+ props.order
19
205
  ]);
20
206
  }, { "module": "@nativescript-community/octane" });
21
207
  //#endregion
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "buildId": "f6769804-c57f-408a-9066-2cfebe36da4e",
3
+ "buildId": "933ede86-144c-4cb6-9763-762ae7aea462",
4
4
  "mode": "production",
5
5
  "capabilities": {
6
6
  "independentHydration": false
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "buildId": "bd95f265-682a-446a-a284-1f3419b2fb06",
3
+ "buildId": "10dfc210-9d43-431b-bdf5-f06486fddbf1",
4
4
  "mode": "production",
5
5
  "capabilities": {
6
6
  "independentHydration": false
@@ -0,0 +1,22 @@
1
+ import type { NativeScriptConfig } from '@nativescript/core'
2
+
3
+ // Plugin-level NativeScript config — read by the CLI's plugin discovery for
4
+ // every app that depends on @octane-xplat/richtext directly. Declares the
5
+ // iOS Swift facade's engine dependency so consuming apps don't wire it
6
+ // themselves.
7
+ export default {
8
+ ios: {
9
+ SPMPackages: [
10
+ {
11
+ name: 'AztecEditor-iOS',
12
+ libs: ['Aztec'],
13
+ repositoryURL:
14
+ 'https://github.com/wordpress-mobile/AztecEditor-iOS',
15
+ // '#' prefix selects a revision requirement in the generated
16
+ // pbxproj — develop @ 44aeac6 (podspec version 1.20.0, first
17
+ // with SPM support). MPL-2.0; see platforms/ios/UPSTREAM.md.
18
+ version: '#44aeac606a3cff6d6ecb1d49ea3f9068082567e1',
19
+ },
20
+ ],
21
+ },
22
+ } as NativeScriptConfig
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@octane-xplat/richtext",
3
- "version": "0.9.0",
4
- "description": "Native rich-text editing leaf for Octane xplat — WordPress Aztec on Android (iOS stubbed, deferred)",
3
+ "version": "0.11.0",
4
+ "description": "Native rich-text editing leaf for Octane xplat — Android Aztec and AppKit WKWebView StarterKit",
5
5
  "keywords": [
6
6
  "android",
7
7
  "aztec",
@@ -23,13 +23,14 @@
23
23
  "dist",
24
24
  "types",
25
25
  "src",
26
- "platforms"
26
+ "platforms",
27
+ "nativescript.config.ts"
27
28
  ],
28
29
  "type": "module",
29
30
  "exports": {
30
31
  ".": {
31
32
  "macos": {
32
- "types": "./types/index.d.ts",
33
+ "types": "./types/index.macos.d.ts",
33
34
  "default": "./src/index.macos.ts"
34
35
  },
35
36
  "web": {
@@ -42,6 +43,14 @@
42
43
  },
43
44
  "types": "./types/index.d.ts",
44
45
  "default": "./dist/native/index.js"
46
+ },
47
+ "./macos-host": {
48
+ "types": "./types/macos-host.d.ts",
49
+ "default": "./src/NativeEditor.macos.tsx"
50
+ },
51
+ "./browser-transport": {
52
+ "types": "./types/browser-transport.d.ts",
53
+ "default": "./src/browser-transport.web.ts"
45
54
  }
46
55
  },
47
56
  "publishConfig": {
@@ -50,7 +59,10 @@
50
59
  "devDependencies": {
51
60
  "@nativescript-community/octane": "0.2.4",
52
61
  "@nativescript/core": "9.1.2",
62
+ "@octane-xplat/macos-renderer": "0.11.0",
53
63
  "@octanejs/vite-plugin": "0.1.61",
64
+ "@tiptap/core": "3.28.0",
65
+ "@tiptap/starter-kit": "3.28.0",
54
66
  "octane": "0.6.3",
55
67
  "typescript": "5.9.3",
56
68
  "vite": "8.3.0"
@@ -77,7 +89,17 @@
77
89
  "ios": "9.1.0"
78
90
  }
79
91
  },
92
+ "xplat": {
93
+ "macos": {
94
+ "frameworks": [
95
+ "WebKit"
96
+ ]
97
+ }
98
+ },
80
99
  "scripts": {
81
- "build": "vite build && vite build --mode native && tsc -p tsconfig.types.json && node ../../scripts/check-native-dist.mjs"
100
+ "build": "vite build && vite build --mode native && tsc -p tsconfig.types.json && node ../../scripts/check-native-dist.mjs && node build-browser.mjs",
101
+ "test": "node --test test/*.test.mjs",
102
+ "test:macos": "node test/verify-wk.mjs",
103
+ "test:packed": "node test/packed-consumer.mjs"
82
104
  }
83
105
  }