@trypattern/sdk 0.1.32 → 0.1.33
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/dist/components/FilePreview.d.ts +10 -0
- package/dist/components/FilePreview.js +36 -0
- package/dist/components/Image.d.ts +2 -1
- package/dist/components/Image.js +5 -2
- package/dist/components/Menu.js +2 -2
- package/dist/components/SegmentedControl.js +2 -2
- package/dist/flows/browser.js +7 -0
- package/dist/media.d.ts +2 -1
- package/dist/media.js +4 -4
- package/dist/react.d.ts +1 -0
- package/dist/react.js +1 -0
- package/dist/rules/lintPlugin.js +1 -0
- package/dist/server/tables.js +8 -1
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PickedFile } from '../files.ts';
|
|
2
|
+
import type { Placement } from './Placement.ts';
|
|
3
|
+
type FilePreviewProps = {
|
|
4
|
+
file: PickedFile;
|
|
5
|
+
alt: string;
|
|
6
|
+
aspect?: number;
|
|
7
|
+
style?: Placement;
|
|
8
|
+
};
|
|
9
|
+
export declare function FilePreview({ file, alt, aspect, style }: FilePreviewProps): import("react").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as stylex from '@stylexjs/stylex';
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { pickedFileOf } from "../files.js";
|
|
5
|
+
import { colors } from "../theme/tokens.stylex.js";
|
|
6
|
+
export function FilePreview({ file, alt, aspect = 1, style }) {
|
|
7
|
+
const [shown, setShown] = useState(null);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const picked = pickedFileOf(file.id);
|
|
10
|
+
if (picked === undefined || !picked.type.startsWith('image/'))
|
|
11
|
+
return;
|
|
12
|
+
const url = URL.createObjectURL(picked);
|
|
13
|
+
setShown({ id: file.id, url });
|
|
14
|
+
return () => URL.revokeObjectURL(url);
|
|
15
|
+
}, [file.id]);
|
|
16
|
+
const url = shown?.id === file.id ? shown.url : null;
|
|
17
|
+
return (_jsx("span", { ...stylex.props(styles.frame, styles.ratio(aspect), style), children: url === null ? null : (_jsx("img", { alt: alt, src: url, ...stylex.props(styles.image) })) }));
|
|
18
|
+
}
|
|
19
|
+
const styles = stylex.create({
|
|
20
|
+
frame: {
|
|
21
|
+
position: 'relative',
|
|
22
|
+
display: 'block',
|
|
23
|
+
width: '100%',
|
|
24
|
+
overflow: 'hidden',
|
|
25
|
+
backgroundColor: colors.component
|
|
26
|
+
},
|
|
27
|
+
ratio: (ratio) => ({
|
|
28
|
+
aspectRatio: String(ratio)
|
|
29
|
+
}),
|
|
30
|
+
image: {
|
|
31
|
+
display: 'block',
|
|
32
|
+
width: '100%',
|
|
33
|
+
height: '100%',
|
|
34
|
+
objectFit: 'cover'
|
|
35
|
+
}
|
|
36
|
+
});
|
|
@@ -5,7 +5,8 @@ type ImageProps = {
|
|
|
5
5
|
sizes: string;
|
|
6
6
|
priority?: boolean;
|
|
7
7
|
aspect?: number;
|
|
8
|
+
origin?: string;
|
|
8
9
|
style?: Placement;
|
|
9
10
|
};
|
|
10
|
-
export declare function Image({ image, sizes, priority, aspect, style }: ImageProps): import("react").JSX.Element;
|
|
11
|
+
export declare function Image({ image, sizes, priority, aspect, origin, style }: ImageProps): import("react").JSX.Element;
|
|
11
12
|
export {};
|
package/dist/components/Image.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { imageSources, transformsOn } from "../media.js";
|
|
5
5
|
import { breakpoints, colors, motion } from "../theme/tokens.stylex.js";
|
|
6
|
-
export function Image({ image, sizes, priority = false, aspect, style }) {
|
|
6
|
+
export function Image({ image, sizes, priority = false, aspect, origin, style }) {
|
|
7
7
|
const key = image?.key ?? null;
|
|
8
8
|
const [seen, setSeen] = useState({
|
|
9
9
|
key,
|
|
@@ -19,7 +19,10 @@ export function Image({ image, sizes, priority = false, aspect, style }) {
|
|
|
19
19
|
}
|
|
20
20
|
const sources = imageSources(image, {
|
|
21
21
|
aspect,
|
|
22
|
-
transforms:
|
|
22
|
+
transforms: origin === undefined
|
|
23
|
+
? servedWithTransforms()
|
|
24
|
+
: transformsOn(new URL(origin).hostname),
|
|
25
|
+
...(origin === undefined ? {} : { origin: new URL(origin).origin })
|
|
23
26
|
});
|
|
24
27
|
return (_jsxs("span", { ...stylex.props(styles.frame, styles.ratio(ratio), style), children: [image.placeholder === null ? null : (_jsx("span", { "aria-hidden": "true", ...stylex.props(styles.placeholder(image.placeholder)) })), _jsx("img", { ref: (element) => {
|
|
25
28
|
if (status === 'loading' &&
|
package/dist/components/Menu.js
CHANGED
|
@@ -2,11 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Menu as BaseMenu } from '@base-ui/react/menu';
|
|
3
3
|
import * as stylex from '@stylexjs/stylex';
|
|
4
4
|
import { colors, controls, layers, space } from "../theme/tokens.stylex.js";
|
|
5
|
-
import { controlSizes, focusRing, transparentLook } from "./controlLook.js";
|
|
5
|
+
import { buttonCorners, controlSizes, focusRing, transparentLook } from "./controlLook.js";
|
|
6
6
|
import { MenuItems } from "./MenuItems.js";
|
|
7
7
|
import { Popup } from "./Popup.js";
|
|
8
8
|
export function Menu({ trigger, items, size = 'md', style }) {
|
|
9
|
-
return (_jsxs(BaseMenu.Root, { children: [_jsx(BaseMenu.Trigger, { className: (state) => stylex.props(styles.trigger, controlSizes[size], triggerPaddings[size], transparentLook.rest, transparentLook.hoverable, state.open && transparentLook.open, styles.triggerText, focusRing.visible, style).className, children: trigger }), _jsx(BaseMenu.Portal, { children: _jsx(BaseMenu.Positioner, { side: "bottom", align: "start", sideOffset: 4, className: stylex.props(styles.positioner).className, children: _jsx(BaseMenu.Popup, { render: (props, state) => (_jsx(Popup, { ...props, kind: "menu", isOpen: state.open, transitionStatus: state.transitionStatus })), children: _jsx(MenuItems, { items: items, primitive: "Menu" }) }) }) })] }));
|
|
9
|
+
return (_jsxs(BaseMenu.Root, { children: [_jsx(BaseMenu.Trigger, { className: (state) => stylex.props(styles.trigger, controlSizes[size], buttonCorners[size], triggerPaddings[size], transparentLook.rest, transparentLook.hoverable, state.open && transparentLook.open, styles.triggerText, focusRing.visible, style).className, children: trigger }), _jsx(BaseMenu.Portal, { children: _jsx(BaseMenu.Positioner, { side: "bottom", align: "start", sideOffset: 4, className: stylex.props(styles.positioner).className, children: _jsx(BaseMenu.Popup, { render: (props, state) => (_jsx(Popup, { ...props, kind: "menu", isOpen: state.open, transitionStatus: state.transitionStatus })), children: _jsx(MenuItems, { items: items, primitive: "Menu" }) }) }) })] }));
|
|
10
10
|
}
|
|
11
11
|
const styles = stylex.create({
|
|
12
12
|
trigger: {
|
|
@@ -4,13 +4,13 @@ import { RadioGroup } from '@base-ui/react/radio-group';
|
|
|
4
4
|
import * as stylex from '@stylexjs/stylex';
|
|
5
5
|
import { borders, colors, fontWeights, motion, radii } from "../theme/tokens.stylex.js";
|
|
6
6
|
import { interact } from "./interaction.js";
|
|
7
|
-
import { controlSizes, focusRing } from "./controlLook.js";
|
|
7
|
+
import { buttonCorners, controlSizes, focusRing } from "./controlLook.js";
|
|
8
8
|
export function SegmentedControl({ label, value, options, size = 'md', disabled = false, onChange, style }) {
|
|
9
9
|
const index = Math.max(0, options.findIndex((option) => option.value === value));
|
|
10
10
|
return (_jsxs(RadioGroup, { "aria-label": label, value: value, disabled: disabled, onValueChange: (next) => {
|
|
11
11
|
interact({ primitive: 'SegmentedControl', event: 'change', label });
|
|
12
12
|
onChange(next);
|
|
13
|
-
}, className: stylex.props(styles.group, style).className, children: [_jsx("span", { ...stylex.props(styles.indicator(index, options.length)) }), options.map((option) => (_jsx(Radio.Root, { value: option.value, className: (state) => stylex.props(styles.option, controlSizes[size], !disabled && styles.hoverable, state.checked && styles.optionChecked, disabled && styles.disabled, focusRing.visible).className, children: option.label }, option.value)))] }));
|
|
13
|
+
}, className: stylex.props(styles.group, style).className, children: [_jsx("span", { ...stylex.props(styles.indicator(index, options.length)) }), options.map((option) => (_jsx(Radio.Root, { value: option.value, className: (state) => stylex.props(styles.option, controlSizes[size], buttonCorners[size], !disabled && styles.hoverable, state.checked && styles.optionChecked, disabled && styles.disabled, focusRing.visible).className, children: option.label }, option.value)))] }));
|
|
14
14
|
}
|
|
15
15
|
const styles = stylex.create({
|
|
16
16
|
group: {
|
package/dist/flows/browser.js
CHANGED
|
@@ -4,6 +4,7 @@ export const viewports = {
|
|
|
4
4
|
compact: { width: 390, height: 844, deviceScaleFactor: 2 }
|
|
5
5
|
};
|
|
6
6
|
export const viewportNames = ['desktop', 'compact'];
|
|
7
|
+
const STAND_IN_PHOTO = '<svg xmlns="http://www.w3.org/2000/svg" width="4" height="3"><rect width="4" height="3" fill="#d9d4c8"/></svg>';
|
|
7
8
|
const QUIET_NETWORK_MS = 250;
|
|
8
9
|
const SETTLE_TIMEOUT_MS = 10_000;
|
|
9
10
|
const HOOK_TIMEOUT_MS = 10_000;
|
|
@@ -122,6 +123,12 @@ export async function openApp(browser, baseUrl, path, viewport, signedInAs, memo
|
|
|
122
123
|
});
|
|
123
124
|
}, { ...memory, signedInAs });
|
|
124
125
|
}
|
|
126
|
+
await context.route((url) => url.origin !== new URL(baseUrl).origin, (route) => route.request().resourceType() === 'image'
|
|
127
|
+
? route.fulfill({
|
|
128
|
+
contentType: 'image/svg+xml',
|
|
129
|
+
body: STAND_IN_PHOTO
|
|
130
|
+
})
|
|
131
|
+
: route.continue());
|
|
125
132
|
const page = await context.newPage();
|
|
126
133
|
const problems = [];
|
|
127
134
|
recordProblems(page, problems);
|
package/dist/media.d.ts
CHANGED
|
@@ -40,7 +40,8 @@ export type ImageSources = {
|
|
|
40
40
|
width: number;
|
|
41
41
|
height: number;
|
|
42
42
|
};
|
|
43
|
-
export declare function imageSources(image: MediaImage, { aspect, transforms }: {
|
|
43
|
+
export declare function imageSources(image: MediaImage, { aspect, transforms, origin }: {
|
|
44
44
|
aspect?: number | undefined;
|
|
45
45
|
transforms: boolean;
|
|
46
|
+
origin?: string;
|
|
46
47
|
}): ImageSources;
|
package/dist/media.js
CHANGED
|
@@ -46,14 +46,14 @@ function transformed(key, width, aspect) {
|
|
|
46
46
|
];
|
|
47
47
|
return `/cdn-cgi/image/${options.join(',')}${mediaPath(key)}`;
|
|
48
48
|
}
|
|
49
|
-
export function imageSources(image, { aspect, transforms }) {
|
|
49
|
+
export function imageSources(image, { aspect, transforms, origin = '' }) {
|
|
50
50
|
const largest = largestWidth(image, aspect);
|
|
51
51
|
const height = aspect === undefined
|
|
52
52
|
? image.height
|
|
53
53
|
: Math.max(1, Math.round(largest / aspect));
|
|
54
54
|
if (!transforms) {
|
|
55
55
|
return {
|
|
56
|
-
src: mediaPath(image.key)
|
|
56
|
+
src: `${origin}${mediaPath(image.key)}`,
|
|
57
57
|
srcSet: undefined,
|
|
58
58
|
width: largest,
|
|
59
59
|
height
|
|
@@ -64,9 +64,9 @@ export function imageSources(image, { aspect, transforms }) {
|
|
|
64
64
|
largest
|
|
65
65
|
].filter((width, index, all) => all.indexOf(width) === index);
|
|
66
66
|
return {
|
|
67
|
-
src: transformed(image.key, Math.min(FALLBACK_WIDTH, largest), aspect)
|
|
67
|
+
src: `${origin}${transformed(image.key, Math.min(FALLBACK_WIDTH, largest), aspect)}`,
|
|
68
68
|
srcSet: widths
|
|
69
|
-
.map((width) => `${transformed(image.key, width, aspect)} ${width}w`)
|
|
69
|
+
.map((width) => `${origin}${transformed(image.key, width, aspect)} ${width}w`)
|
|
70
70
|
.join(', '),
|
|
71
71
|
width: largest,
|
|
72
72
|
height
|
package/dist/react.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export { Form } from './components/Form.tsx';
|
|
|
25
25
|
export { Icon } from './components/Icon.tsx';
|
|
26
26
|
export { IconButton } from './components/IconButton.tsx';
|
|
27
27
|
export { FilePicker } from './components/FilePicker.tsx';
|
|
28
|
+
export { FilePreview } from './components/FilePreview.tsx';
|
|
28
29
|
export { Gallery } from './components/Gallery.tsx';
|
|
29
30
|
export { Header } from './components/Header.tsx';
|
|
30
31
|
export { Image } from './components/Image.tsx';
|
package/dist/react.js
CHANGED
|
@@ -23,6 +23,7 @@ export { Form } from "./components/Form.js";
|
|
|
23
23
|
export { Icon } from "./components/Icon.js";
|
|
24
24
|
export { IconButton } from "./components/IconButton.js";
|
|
25
25
|
export { FilePicker } from "./components/FilePicker.js";
|
|
26
|
+
export { FilePreview } from "./components/FilePreview.js";
|
|
26
27
|
export { Gallery } from "./components/Gallery.js";
|
|
27
28
|
export { Header } from "./components/Header.js";
|
|
28
29
|
export { Image } from "./components/Image.js";
|
package/dist/rules/lintPlugin.js
CHANGED
package/dist/server/tables.js
CHANGED
|
@@ -100,6 +100,9 @@ export function seedSql(tables, seed) {
|
|
|
100
100
|
});
|
|
101
101
|
return [...users, ...rowsSql].join('\n');
|
|
102
102
|
}
|
|
103
|
+
function startedAt(secondsAgo) {
|
|
104
|
+
return `strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-${secondsAgo} seconds')`;
|
|
105
|
+
}
|
|
103
106
|
export function starterSql(tables, rows) {
|
|
104
107
|
return Object.values(tables)
|
|
105
108
|
.flatMap((table) => {
|
|
@@ -108,7 +111,11 @@ export function starterSql(tables, rows) {
|
|
|
108
111
|
return [];
|
|
109
112
|
const keys = ['id', 'createdAt', ...Object.keys(table.columns)];
|
|
110
113
|
const values = listed
|
|
111
|
-
.map((row) => `(${keys
|
|
114
|
+
.map((row, index) => `(${keys
|
|
115
|
+
.map((key) => key === 'createdAt'
|
|
116
|
+
? startedAt(listed.length - 1 - index)
|
|
117
|
+
: sqlLiteral((row[key] ?? null)))
|
|
118
|
+
.join(', ')})`)
|
|
112
119
|
.join(',\n ');
|
|
113
120
|
return [
|
|
114
121
|
`INSERT OR IGNORE INTO ${snakeCase(table.name)} (${keys.map(snakeCase).join(', ')}) VALUES\n ${values};`
|