@colixsystems/widget-sdk 0.63.0 → 0.64.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/contract.cjs +9 -2
- package/dist/contract.js +9 -2
- package/dist/datetimepicker-format.js +22 -3
- package/dist/datetimepicker.js +14 -3
- package/dist/datetimepicker.native.js +15 -3
- package/dist/hooks.js +11 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,7 +53,11 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
53
53
|
|
|
54
54
|
## Status
|
|
55
55
|
|
|
56
|
-
`v0.
|
|
56
|
+
`v0.64.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**.
|
|
57
|
+
|
|
58
|
+
### What's new in 0.64.0
|
|
59
|
+
|
|
60
|
+
**`<DateTimePicker>` themes itself — legible on dark surfaces (sc-3370).** The primitive now derives its colours from the workspace theme on BOTH hosts instead of hardcoding them: the text uses `colors.onSurface`, the border uses `colors.border`, and on web the input's `color-scheme` follows the theme so the browser's built-in date UI (the `yyyy-mm-dd` edit segments and the calendar icon) stays legible on a dark surface. Previously the web input used `color: inherit` with no `color-scheme` and the native trigger set no text colour, so on a dark-themed app the field rendered dark-on-dark and unreadable — with no prop an author could set to fix it. **No prop changed**: the seven-prop contract (`value, onChange, mode, minimumDate, maximumDate, disabled, accessibilityLabel`) is unchanged, and you do NOT style the field yourself — never reach for raw CSS or `document`, which the widget linter rejects. `CONTRACT.version` → `1.43.0`. Behavioural fix, additive.
|
|
57
61
|
|
|
58
62
|
### What's new in 0.63.0
|
|
59
63
|
|
package/dist/contract.cjs
CHANGED
|
@@ -823,7 +823,7 @@ const PRIMITIVES = [
|
|
|
823
823
|
{
|
|
824
824
|
name: "DateTimePicker",
|
|
825
825
|
description:
|
|
826
|
-
'Cross-platform date / time / datetime picker. `<DateTimePicker value={iso} onChange={iso => …} mode="date" | "time" | "datetime" />`. The value prop and the onChange callback both speak ISO 8601 strings (the datastore wire format) — authors never round-trip through `new Date()`. Web renders the browser\'s native `<input type="date|time|datetime-local">` directly (react-native-web has no mapping for the RN datetimepicker library); native uses @react-native-community/datetimepicker.',
|
|
826
|
+
'Cross-platform date / time / datetime picker. `<DateTimePicker value={iso} onChange={iso => …} mode="date" | "time" | "datetime" />`. The value prop and the onChange callback both speak ISO 8601 strings (the datastore wire format) — authors never round-trip through `new Date()`. Web renders the browser\'s native `<input type="date|time|datetime-local">` directly (react-native-web has no mapping for the RN datetimepicker library); native uses @react-native-community/datetimepicker. The field themes itself from the workspace theme — text uses `colors.onSurface`, the border `colors.border`, and on web `color-scheme` follows the theme so the browser\'s built-in date UI stays legible on a dark surface; never style it with raw CSS or `document`.',
|
|
827
827
|
rnComponent: "@react-native-community/datetimepicker",
|
|
828
828
|
docsUrl: "https://github.com/react-native-datetimepicker/datetimepicker",
|
|
829
829
|
},
|
|
@@ -1919,7 +1919,14 @@ const CONTRACT = deepFreeze({
|
|
|
1919
1919
|
// default false): declares that the widget renders its own section header,
|
|
1920
1920
|
// so the app-builder places it as a whole section without stacking a
|
|
1921
1921
|
// heading above it. Additive — existing manifests omit it and read false.
|
|
1922
|
-
|
|
1922
|
+
// 1.43.0 (sc-3370) — the `<DateTimePicker>` primitive now themes itself from
|
|
1923
|
+
// the workspace theme on both hosts: text uses `colors.onSurface`, the
|
|
1924
|
+
// border `colors.border`, and the web input's `color-scheme` follows the
|
|
1925
|
+
// theme so the browser's built-in date UI stays legible on a dark surface.
|
|
1926
|
+
// Previously it hardcoded `color: inherit` / an unset scheme (web) and an
|
|
1927
|
+
// uncoloured trigger (native), rendering dark-on-dark. No prop changed —
|
|
1928
|
+
// behavioural fix, additive.
|
|
1929
|
+
version: "1.43.0",
|
|
1923
1930
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
1924
1931
|
hooks: HOOKS,
|
|
1925
1932
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -823,7 +823,7 @@ const PRIMITIVES = [
|
|
|
823
823
|
{
|
|
824
824
|
name: "DateTimePicker",
|
|
825
825
|
description:
|
|
826
|
-
'Cross-platform date / time / datetime picker. `<DateTimePicker value={iso} onChange={iso => …} mode="date" | "time" | "datetime" />`. The value prop and the onChange callback both speak ISO 8601 strings (the datastore wire format) — authors never round-trip through `new Date()`. Web renders the browser\'s native `<input type="date|time|datetime-local">` directly (react-native-web has no mapping for the RN datetimepicker library); native uses @react-native-community/datetimepicker.',
|
|
826
|
+
'Cross-platform date / time / datetime picker. `<DateTimePicker value={iso} onChange={iso => …} mode="date" | "time" | "datetime" />`. The value prop and the onChange callback both speak ISO 8601 strings (the datastore wire format) — authors never round-trip through `new Date()`. Web renders the browser\'s native `<input type="date|time|datetime-local">` directly (react-native-web has no mapping for the RN datetimepicker library); native uses @react-native-community/datetimepicker. The field themes itself from the workspace theme — text uses `colors.onSurface`, the border `colors.border`, and on web `color-scheme` follows the theme so the browser\'s built-in date UI stays legible on a dark surface; never style it with raw CSS or `document`.',
|
|
827
827
|
rnComponent: "@react-native-community/datetimepicker",
|
|
828
828
|
docsUrl: "https://github.com/react-native-datetimepicker/datetimepicker",
|
|
829
829
|
},
|
|
@@ -1919,7 +1919,14 @@ const CONTRACT = deepFreeze({
|
|
|
1919
1919
|
// default false): declares that the widget renders its own section header,
|
|
1920
1920
|
// so the app-builder places it as a whole section without stacking a
|
|
1921
1921
|
// heading above it. Additive — existing manifests omit it and read false.
|
|
1922
|
-
|
|
1922
|
+
// 1.43.0 (sc-3370) — the `<DateTimePicker>` primitive now themes itself from
|
|
1923
|
+
// the workspace theme on both hosts: text uses `colors.onSurface`, the
|
|
1924
|
+
// border `colors.border`, and the web input's `color-scheme` follows the
|
|
1925
|
+
// theme so the browser's built-in date UI stays legible on a dark surface.
|
|
1926
|
+
// Previously it hardcoded `color: inherit` / an unset scheme (web) and an
|
|
1927
|
+
// uncoloured trigger (native), rendering dark-on-dark. No prop changed —
|
|
1928
|
+
// behavioural fix, additive.
|
|
1929
|
+
version: "1.43.0",
|
|
1923
1930
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
1924
1931
|
hooks: HOOKS,
|
|
1925
1932
|
primitives: PRIMITIVES,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// REQ-WSDK-PLATFORM §6 — pure
|
|
1
|
+
// REQ-WSDK-PLATFORM §6 — pure, RN-free helpers for the `<DateTimePicker>`.
|
|
2
2
|
//
|
|
3
|
-
// Split out of
|
|
3
|
+
// Split out of the primitive so the formatting + theming contract can be
|
|
4
4
|
// unit-tested without importing react-native / the RN datetimepicker library
|
|
5
5
|
// (neither is installed in this package's node tree). No React, no RN here —
|
|
6
|
-
// just Date math and
|
|
6
|
+
// just Date math, string shaping, and a colour-luminance test.
|
|
7
7
|
|
|
8
8
|
export function parseToDate(value) {
|
|
9
9
|
if (value == null || value === "") return new Date();
|
|
@@ -51,3 +51,22 @@ export function formatDisplayLabel(value, mode) {
|
|
|
51
51
|
if (Number.isNaN(d.getTime())) return String(value);
|
|
52
52
|
return `${formatToIso(d, "date")} ${formatToIso(d, "time")}`;
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
// Perceived-luminance test for a hex colour (`#rgb` or `#rrggbb`). The web
|
|
56
|
+
// picker uses it to choose a matching `color-scheme` so the browser's built-in
|
|
57
|
+
// date UI (edit segments + calendar icon) stays legible on a dark themed
|
|
58
|
+
// surface. Anything unparseable is treated as light so a light theme is never
|
|
59
|
+
// darkened.
|
|
60
|
+
export function isDarkColor(hex) {
|
|
61
|
+
if (typeof hex !== "string") return false;
|
|
62
|
+
let h = hex.trim().replace(/^#/, "");
|
|
63
|
+
if (h.length === 3) {
|
|
64
|
+
h = h.split("").map((c) => c + c).join("");
|
|
65
|
+
}
|
|
66
|
+
if (h.length !== 6 || /[^0-9a-fA-F]/.test(h)) return false;
|
|
67
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
68
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
69
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
70
|
+
const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
|
|
71
|
+
return luminance < 0.5;
|
|
72
|
+
}
|
package/dist/datetimepicker.js
CHANGED
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
// readers can locate the input by its label.
|
|
26
26
|
|
|
27
27
|
import React from "react";
|
|
28
|
+
import { useHostTheme } from "./hooks.js";
|
|
29
|
+
import { isDarkColor } from "./datetimepicker-format.js";
|
|
30
|
+
import { DEFAULT_THEME_TOKENS } from "./_theme-tokens.js";
|
|
28
31
|
|
|
29
32
|
const MODE_TO_INPUT_TYPE = {
|
|
30
33
|
date: "date",
|
|
@@ -80,6 +83,7 @@ export function DateTimePicker({
|
|
|
80
83
|
disabled,
|
|
81
84
|
accessibilityLabel,
|
|
82
85
|
}) {
|
|
86
|
+
const theme = useHostTheme() || DEFAULT_THEME_TOKENS;
|
|
83
87
|
const effectiveMode = mode === "time" || mode === "datetime" ? mode : "date";
|
|
84
88
|
const inputType = MODE_TO_INPUT_TYPE[effectiveMode];
|
|
85
89
|
const inputValue = _isoToInputValue(value, effectiveMode);
|
|
@@ -128,7 +132,13 @@ export function DateTimePicker({
|
|
|
128
132
|
// Inline styles match the SDK's other web-only primitives — the host's
|
|
129
133
|
// form widgets wrap this in their own labelled field, so the input just
|
|
130
134
|
// needs to look like a normal text input. `cursor: pointer` signals the
|
|
131
|
-
// whole field is the click affordance (sc-1878).
|
|
135
|
+
// whole field is the click affordance (sc-1878). Colours come from the
|
|
136
|
+
// theme so the field is legible on any surface (sc-3370); `colorScheme`
|
|
137
|
+
// steers the browser's built-in date UI (edit segments + calendar icon).
|
|
138
|
+
// The scheme keys off the theme's TEXT colour (onSurface, which the host
|
|
139
|
+
// already picked to contrast the surface) rather than re-deriving dark-vs-
|
|
140
|
+
// light from the surface with a second luminance formula that could disagree
|
|
141
|
+
// with the host: light text ⇒ dark surface ⇒ dark scheme.
|
|
132
142
|
const style = {
|
|
133
143
|
boxSizing: "border-box",
|
|
134
144
|
width: "100%",
|
|
@@ -136,11 +146,12 @@ export function DateTimePicker({
|
|
|
136
146
|
padding: "8px 12px",
|
|
137
147
|
fontSize: 16,
|
|
138
148
|
fontFamily: "inherit",
|
|
139
|
-
color:
|
|
149
|
+
color: theme.colors.onSurface,
|
|
140
150
|
backgroundColor: "transparent",
|
|
151
|
+
colorScheme: isDarkColor(theme.colors.onSurface) ? "light" : "dark",
|
|
141
152
|
borderWidth: 1,
|
|
142
153
|
borderStyle: "solid",
|
|
143
|
-
borderColor:
|
|
154
|
+
borderColor: theme.colors.border,
|
|
144
155
|
borderRadius: 6,
|
|
145
156
|
outline: "none",
|
|
146
157
|
cursor: disabled ? "default" : "pointer",
|
|
@@ -32,6 +32,8 @@ import {
|
|
|
32
32
|
formatToIso,
|
|
33
33
|
formatDisplayLabel,
|
|
34
34
|
} from "./datetimepicker-format.js";
|
|
35
|
+
import { useHostTheme } from "./hooks.js";
|
|
36
|
+
import { DEFAULT_THEME_TOKENS } from "./_theme-tokens.js";
|
|
35
37
|
|
|
36
38
|
const styles = StyleSheet.create({
|
|
37
39
|
trigger: {
|
|
@@ -39,7 +41,6 @@ const styles = StyleSheet.create({
|
|
|
39
41
|
paddingVertical: 8,
|
|
40
42
|
paddingHorizontal: 12,
|
|
41
43
|
borderWidth: 1,
|
|
42
|
-
borderColor: "rgba(0, 0, 0, 0.16)",
|
|
43
44
|
borderRadius: 6,
|
|
44
45
|
justifyContent: "center",
|
|
45
46
|
},
|
|
@@ -57,6 +58,7 @@ export function DateTimePicker({
|
|
|
57
58
|
disabled,
|
|
58
59
|
accessibilityLabel,
|
|
59
60
|
}) {
|
|
61
|
+
const theme = useHostTheme() || DEFAULT_THEME_TOKENS;
|
|
60
62
|
const effectiveMode = mode === "time" || mode === "datetime" ? mode : "date";
|
|
61
63
|
const [open, setOpen] = useState(false);
|
|
62
64
|
const dateValue = useMemo(() => parseToDate(value), [value]);
|
|
@@ -89,11 +91,21 @@ export function DateTimePicker({
|
|
|
89
91
|
accessibilityRole: "button",
|
|
90
92
|
accessibilityLabel,
|
|
91
93
|
accessibilityState: { disabled: !!disabled },
|
|
92
|
-
|
|
94
|
+
// Themed border + text so the trigger is legible on any surface (sc-3370).
|
|
95
|
+
style: [
|
|
96
|
+
styles.trigger,
|
|
97
|
+
{ borderColor: theme.colors.border },
|
|
98
|
+
disabled && styles.triggerDisabled,
|
|
99
|
+
],
|
|
93
100
|
},
|
|
94
101
|
React.createElement(
|
|
95
102
|
Text,
|
|
96
|
-
{
|
|
103
|
+
{
|
|
104
|
+
style: [
|
|
105
|
+
isEmpty ? styles.placeholder : styles.label,
|
|
106
|
+
{ color: theme.colors.onSurface },
|
|
107
|
+
],
|
|
108
|
+
},
|
|
97
109
|
formatDisplayLabel(value, effectiveMode),
|
|
98
110
|
),
|
|
99
111
|
);
|
package/dist/hooks.js
CHANGED
|
@@ -91,6 +91,17 @@ export function useTheme() {
|
|
|
91
91
|
return ctx.workspace.theme;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
// @internal — reads the host theme WITHOUT throwing when no provider is
|
|
95
|
+
// mounted (returns undefined instead), unlike useTheme() which asserts a
|
|
96
|
+
// widget context. Low-level primitives (DateTimePicker) read it so they stay
|
|
97
|
+
// renderable anywhere, applying their own default tokens on the undefined
|
|
98
|
+
// case. Not part of the public widget hook surface — not re-exported from
|
|
99
|
+
// index.js.
|
|
100
|
+
export function useHostTheme() {
|
|
101
|
+
const ctx = useContext(HostWidgetContext);
|
|
102
|
+
return ctx && ctx.workspace ? ctx.workspace.theme : undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
94
105
|
/**
|
|
95
106
|
* REQ-THEME-13 — returns the author-set per-widget style values: the object the
|
|
96
107
|
* host delivers under `props.style`, keyed by the style-field names the widget
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.64.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|