@colixsystems/widget-sdk 0.199.0 → 0.200.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/README.md +5 -1
- package/dist/emoji-picker.js +2 -1
- package/dist/host.d.ts +6 -0
- package/dist/host.js +1 -0
- package/dist/markdown-input.js +6 -1
- package/dist/primitives.js +2 -1
- package/dist/text-field.js +2 -1
- package/dist/text-input-view.js +27 -0
- package/dist/theme-background.cjs +26 -3
- package/dist/theme-background.js +20 -2
- package/dist/touch-input-font-floor.js +22 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,7 +83,11 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
83
83
|
|
|
84
84
|
## Status
|
|
85
85
|
|
|
86
|
-
`v0.
|
|
86
|
+
`v0.200.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
|
|
87
|
+
|
|
88
|
+
### What's new in 0.200.0 (contract 1.159.0)
|
|
89
|
+
|
|
90
|
+
**Host sign-in screen: a logo on the card.** `resolveLoginLogoUrl(login, appLogoUrl)` answers which logo the built-in sign-in card shows: the author's own sign-in logo (`login.logoUrlResolved`, the host's resolution of `login.logoAssetId`, else the pasted `login.logoUrl`), else the app logo the host already resolved, else `null` for the stock mark. Every candidate passes the same scheme allowlist as the sign-in background, so a `javascript:` or `data:` value never reaches either host. It is kept apart from `normaliseLoginDesign` because an app logo alone is not an authored design. Widgets are unaffected: this is the host surface (`@colixsystems/widget-sdk/host`), and the widget contract version does not change.
|
|
87
91
|
|
|
88
92
|
### What's new in 0.199.0 (contract 1.159.0)
|
|
89
93
|
|
package/dist/emoji-picker.js
CHANGED
|
@@ -10,5 +10,6 @@
|
|
|
10
10
|
import * as ReactNative from "react-native-web";
|
|
11
11
|
import { makeEmojiPicker } from "./emoji-picker-view.js";
|
|
12
12
|
import { Overlay } from "./overlay.js";
|
|
13
|
+
import { TextInput } from "./primitives.js";
|
|
13
14
|
|
|
14
|
-
export const EmojiPicker = makeEmojiPicker({ ...ReactNative, Overlay });
|
|
15
|
+
export const EmojiPicker = makeEmojiPicker({ ...ReactNative, TextInput, Overlay });
|
package/dist/host.d.ts
CHANGED
|
@@ -460,6 +460,12 @@ export interface LoginDesign {
|
|
|
460
460
|
/** The sign-in screen's authored design, or null when nothing is configured. */
|
|
461
461
|
export function normaliseLoginDesign(raw: unknown): LoginDesign | null;
|
|
462
462
|
|
|
463
|
+
/** sc-10845 — the sign-in card's logo: the author's own, else the app logo. */
|
|
464
|
+
export function resolveLoginLogoUrl(
|
|
465
|
+
login: unknown,
|
|
466
|
+
appLogoUrl: string | null | undefined,
|
|
467
|
+
): string | null;
|
|
468
|
+
|
|
463
469
|
/** sc-7800 — true when a stored value is a `theme:<path>` colour binding. */
|
|
464
470
|
export function isThemeTokenRef(value: unknown): boolean;
|
|
465
471
|
|
package/dist/host.js
CHANGED
package/dist/markdown-input.js
CHANGED
|
@@ -6,5 +6,10 @@ import * as ReactNative from "react-native-web";
|
|
|
6
6
|
import { makeMarkdownInput } from "./markdown-input-view.js";
|
|
7
7
|
import { RichText } from "./richtext.js";
|
|
8
8
|
import { Overlay } from "./overlay.js";
|
|
9
|
+
import { TextInput } from "./primitives.js";
|
|
9
10
|
|
|
10
|
-
export const MarkdownInput = makeMarkdownInput(
|
|
11
|
+
export const MarkdownInput = makeMarkdownInput(
|
|
12
|
+
{ ...ReactNative, TextInput },
|
|
13
|
+
RichText,
|
|
14
|
+
Overlay,
|
|
15
|
+
);
|
package/dist/primitives.js
CHANGED
|
@@ -40,13 +40,14 @@
|
|
|
40
40
|
// static re-export tracing. Behaviour is identical to the old
|
|
41
41
|
// `react-native` alias path on the web.
|
|
42
42
|
import * as ReactNative from "react-native-web";
|
|
43
|
+
import { makeTextInput } from "./text-input-view.js";
|
|
43
44
|
|
|
44
45
|
export const Text = ReactNative.Text;
|
|
45
46
|
export const View = ReactNative.View;
|
|
46
47
|
export const Pressable = ReactNative.Pressable;
|
|
47
48
|
export const Image = ReactNative.Image;
|
|
48
49
|
export const ScrollView = ReactNative.ScrollView;
|
|
49
|
-
export const TextInput = ReactNative.TextInput;
|
|
50
|
+
export const TextInput = makeTextInput(ReactNative.TextInput);
|
|
50
51
|
// Additional cross-platform primitives the AI agent + handwritten
|
|
51
52
|
// widgets commonly reach for. All work in both react-native-web and
|
|
52
53
|
// native react-native without per-platform code.
|
package/dist/text-field.js
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
|
|
4
4
|
import * as ReactNative from "react-native-web";
|
|
5
5
|
import { makeTextField } from "./text-field-view.js";
|
|
6
|
+
import { TextInput } from "./primitives.js";
|
|
6
7
|
|
|
7
|
-
export const TextField = makeTextField(ReactNative);
|
|
8
|
+
export const TextField = makeTextField({ ...ReactNative, TextInput });
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// The web `<TextInput>`: the host's input with the touch font floor. Native
|
|
2
|
+
// has no focus zoom, so ./primitives.native.js re-exports RN's input as is.
|
|
3
|
+
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { withTouchInputFontFloor } from "./touch-input-font-floor.js";
|
|
6
|
+
|
|
7
|
+
function hasCoarsePointer() {
|
|
8
|
+
return (
|
|
9
|
+
typeof window !== "undefined" &&
|
|
10
|
+
typeof window.matchMedia === "function" &&
|
|
11
|
+
window.matchMedia("(pointer: coarse)").matches
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {any} BaseTextInput react-native-web's `TextInput`.
|
|
17
|
+
* @returns a `TextInput` taking the same props and ref.
|
|
18
|
+
*/
|
|
19
|
+
export function makeTextInput(BaseTextInput) {
|
|
20
|
+
return React.forwardRef(function TextInput({ style, ...rest }, ref) {
|
|
21
|
+
return React.createElement(BaseTextInput, {
|
|
22
|
+
...rest,
|
|
23
|
+
ref,
|
|
24
|
+
style: withTouchInputFontFloor(style, hasCoarsePointer()),
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -68,8 +68,8 @@ function normaliseImageUrl(raw) {
|
|
|
68
68
|
if (typeof raw !== "string") return null;
|
|
69
69
|
const url = raw.trim();
|
|
70
70
|
if (!url) return null;
|
|
71
|
-
// A
|
|
72
|
-
if (
|
|
71
|
+
// A same-origin path; `/\host` and whitespace are foreign hosts to a browser.
|
|
72
|
+
if (/^\/(?![/\\])\S*$/.test(url)) return url;
|
|
73
73
|
return /^https?:\/\/\S+$/i.test(url) ? url : null;
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -135,4 +135,27 @@ function normaliseLoginDesign(raw) {
|
|
|
135
135
|
return configured ? design : null;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
/**
|
|
139
|
+
* sc-10845 — the sign-in card's logo: the author's own, else the app logo,
|
|
140
|
+
* else null. Hosts resolve `logoAssetId` into `logoUrlResolved` first. Not in
|
|
141
|
+
* `normaliseLoginDesign`: an app logo alone is not an authored design.
|
|
142
|
+
*
|
|
143
|
+
* @param {object|null|undefined} login - `themeConfig.login`.
|
|
144
|
+
* @param {string|null|undefined} appLogoUrl - the host's resolved app logo.
|
|
145
|
+
* @returns {string|null}
|
|
146
|
+
*/
|
|
147
|
+
function resolveLoginLogoUrl(login, appLogoUrl) {
|
|
148
|
+
const own =
|
|
149
|
+
login && typeof login === "object"
|
|
150
|
+
? normaliseImageUrl(login.logoUrlResolved) ||
|
|
151
|
+
normaliseImageUrl(login.logoUrl)
|
|
152
|
+
: null;
|
|
153
|
+
return own || normaliseImageUrl(appLogoUrl);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = {
|
|
157
|
+
LOGIN_TEXT_MAX_LENGTH,
|
|
158
|
+
normaliseThemeGradient,
|
|
159
|
+
normaliseLoginDesign,
|
|
160
|
+
resolveLoginLogoUrl,
|
|
161
|
+
};
|
package/dist/theme-background.js
CHANGED
|
@@ -60,8 +60,8 @@ function normaliseImageUrl(raw) {
|
|
|
60
60
|
if (typeof raw !== "string") return null;
|
|
61
61
|
const url = raw.trim();
|
|
62
62
|
if (!url) return null;
|
|
63
|
-
// A
|
|
64
|
-
if (
|
|
63
|
+
// A same-origin path; `/\host` and whitespace are foreign hosts to a browser.
|
|
64
|
+
if (/^\/(?![/\\])\S*$/.test(url)) return url;
|
|
65
65
|
return /^https?:\/\/\S+$/i.test(url) ? url : null;
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -126,3 +126,21 @@ export function normaliseLoginDesign(raw) {
|
|
|
126
126
|
const configured = Object.values(design).some((value) => value !== null);
|
|
127
127
|
return configured ? design : null;
|
|
128
128
|
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* sc-10845 — the sign-in card's logo: the author's own, else the app logo,
|
|
132
|
+
* else null. Hosts resolve `logoAssetId` into `logoUrlResolved` first. Not in
|
|
133
|
+
* `normaliseLoginDesign`: an app logo alone is not an authored design.
|
|
134
|
+
*
|
|
135
|
+
* @param {object|null|undefined} login - `themeConfig.login`.
|
|
136
|
+
* @param {string|null|undefined} appLogoUrl - the host's resolved app logo.
|
|
137
|
+
* @returns {string|null}
|
|
138
|
+
*/
|
|
139
|
+
export function resolveLoginLogoUrl(login, appLogoUrl) {
|
|
140
|
+
const own =
|
|
141
|
+
login && typeof login === "object"
|
|
142
|
+
? normaliseImageUrl(login.logoUrlResolved) ||
|
|
143
|
+
normaliseImageUrl(login.logoUrl)
|
|
144
|
+
: null;
|
|
145
|
+
return own || normaliseImageUrl(appLogoUrl);
|
|
146
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// iOS Safari zooms the page when a focused field's text is under 16px, and
|
|
2
|
+
// never zooms back out. Platform-free so it is testable without a DOM.
|
|
3
|
+
|
|
4
|
+
import { flattenStyle } from "./flatten-style.js";
|
|
5
|
+
|
|
6
|
+
export const MIN_TOUCH_INPUT_FONT_SIZE = 16;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `style` with its font size raised to the touch floor. An unset size is
|
|
10
|
+
* floored too: react-native-web's own input default is 14px.
|
|
11
|
+
*
|
|
12
|
+
* @param {object|Array|null|undefined|false} style
|
|
13
|
+
* @param {boolean} isTouch whether the primary pointer is a finger
|
|
14
|
+
* @returns {object|Array|null|undefined|false} `style` itself when unchanged.
|
|
15
|
+
*/
|
|
16
|
+
export function withTouchInputFontFloor(style, isTouch) {
|
|
17
|
+
if (!isTouch) return style;
|
|
18
|
+
const { fontSize } = flattenStyle(style);
|
|
19
|
+
if (typeof fontSize === "string") return style;
|
|
20
|
+
if (fontSize >= MIN_TOUCH_INPUT_FONT_SIZE) return style;
|
|
21
|
+
return [style, { fontSize: MIN_TOUCH_INPUT_FONT_SIZE }];
|
|
22
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.200.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"homepage": "https://github.com/Colix-AB/AppStudio",
|
|
6
6
|
"type": "module",
|