@symbiote-native/linear-gradient 0.0.0-stage → 0.0.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/LICENSE +21 -0
- package/README.md +42 -2
- package/build/angular/index.d.ts +2 -0
- package/build/angular/index.js +3 -0
- package/build/angular/linear-gradient/index.android.d.ts +4 -0
- package/build/angular/linear-gradient/index.android.js +65 -0
- package/build/angular/linear-gradient/index.d.ts +1 -0
- package/build/angular/linear-gradient/index.ios.d.ts +5 -0
- package/build/angular/linear-gradient/index.ios.js +76 -0
- package/build/angular/linear-gradient/index.js +2 -0
- package/build/angular/linear-gradient/shared.d.ts +12 -0
- package/build/angular/linear-gradient/shared.js +97 -0
- package/build/core/index.d.ts +1 -0
- package/build/core/index.js +1 -0
- package/build/core/linear-gradient.d.ts +33 -0
- package/build/core/linear-gradient.js +105 -0
- package/build/react/index.d.ts +3 -0
- package/build/react/index.js +3 -0
- package/build/react/linear-gradient.d.ts +9 -0
- package/build/react/linear-gradient.js +7 -0
- package/build/solid/index.d.ts +3 -0
- package/build/solid/index.js +3 -0
- package/build/solid/linear-gradient.d.ts +10 -0
- package/build/solid/linear-gradient.js +4 -0
- package/build/svelte/index.d.ts +3 -0
- package/build/svelte/index.js +3 -0
- package/build/svelte/linear-gradient-props.d.ts +6 -0
- package/build/svelte/linear-gradient-props.js +1 -0
- package/build/svelte/linear-gradient.svelte +10 -0
- package/build/svelte/linear-gradient.svelte.d.ts +4 -0
- package/build/vue/index.d.ts +3 -0
- package/build/vue/index.js +3 -0
- package/build/vue/linear-gradient.d.ts +6 -0
- package/build/vue/linear-gradient.js +16 -0
- package/build-ngc/angular/index.d.ts +2 -0
- package/build-ngc/angular/index.js +4 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/angular/linear-gradient/index.android.d.ts +7 -0
- package/build-ngc/angular/linear-gradient/index.android.js +24 -0
- package/build-ngc/angular/linear-gradient/index.android.js.map +1 -0
- package/build-ngc/angular/linear-gradient/index.d.ts +1 -0
- package/build-ngc/angular/linear-gradient/index.ios.d.ts +8 -0
- package/build-ngc/angular/linear-gradient/index.ios.js +37 -0
- package/build-ngc/angular/linear-gradient/index.ios.js.map +1 -0
- package/build-ngc/angular/linear-gradient/index.js +3 -0
- package/build-ngc/angular/linear-gradient/index.js.map +1 -0
- package/build-ngc/angular/linear-gradient/shared.d.ts +15 -0
- package/build-ngc/angular/linear-gradient/shared.js +39 -0
- package/build-ngc/angular/linear-gradient/shared.js.map +1 -0
- package/build-ngc/core/index.d.ts +1 -0
- package/build-ngc/core/index.js +2 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/linear-gradient.d.ts +33 -0
- package/build-ngc/core/linear-gradient.js +106 -0
- package/build-ngc/core/linear-gradient.js.map +1 -0
- package/native-link.json +12 -0
- package/package.json +145 -3
- package/src/angular/index.ts +10 -0
- package/src/angular/linear-gradient/index.android.ts +15 -0
- package/src/angular/linear-gradient/index.ios.ts +32 -0
- package/src/angular/linear-gradient/index.ts +2 -0
- package/src/angular/linear-gradient/shared.ts +27 -0
- package/src/core/index.ts +10 -0
- package/src/core/linear-gradient.ts +184 -0
- package/src/react/index.ts +10 -0
- package/src/react/linear-gradient.ts +18 -0
- package/src/solid/index.ts +10 -0
- package/src/solid/linear-gradient.ts +17 -0
- package/src/svelte/index.ts +10 -0
- package/src/svelte/linear-gradient-props.ts +9 -0
- package/src/svelte/linear-gradient.svelte +10 -0
- package/src/svelte/svelte-ambient.d.ts +6 -0
- package/src/svelte/svelte-compile.test-helper.ts +6 -0
- package/src/vue/index.ts +10 -0
- package/src/vue/linear-gradient.ts +23 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Ядро `LinearGradient`, порт `LinearGradient.tsx` из expo-linear-gradient
|
|
2
|
+
import { Platform, requireNativeViewManager } from 'expo-modules-core';
|
|
3
|
+
import { el } from '@symbiote-native/components';
|
|
4
|
+
import type {
|
|
5
|
+
IAccessibilityProps,
|
|
6
|
+
IAriaProps,
|
|
7
|
+
IDescriptor,
|
|
8
|
+
IResponderProps,
|
|
9
|
+
} from '@symbiote-native/components';
|
|
10
|
+
import {
|
|
11
|
+
expoViewManagerName,
|
|
12
|
+
flattenStyle,
|
|
13
|
+
processColor,
|
|
14
|
+
styleOfProps,
|
|
15
|
+
tryRegisterNativeView,
|
|
16
|
+
} from '@symbiote-native/engine';
|
|
17
|
+
import type {
|
|
18
|
+
IColorValue,
|
|
19
|
+
IStyleProp,
|
|
20
|
+
ISymbioteEvent,
|
|
21
|
+
IViewStyle,
|
|
22
|
+
} from '@symbiote-native/engine';
|
|
23
|
+
|
|
24
|
+
export const LINEAR_GRADIENT_MODULE_NAME = 'ExpoLinearGradient';
|
|
25
|
+
|
|
26
|
+
export type INativeLinearGradientPoint = [x: number, y: number];
|
|
27
|
+
|
|
28
|
+
/** Доли размера градиента от 0 до 1, объект `{ x, y }` или пара `[x, y]` */
|
|
29
|
+
export type ILinearGradientPoint =
|
|
30
|
+
| { x: number; y: number }
|
|
31
|
+
| INativeLinearGradientPoint;
|
|
32
|
+
|
|
33
|
+
export type ILinearGradientProps = IAccessibilityProps &
|
|
34
|
+
IAriaProps &
|
|
35
|
+
IResponderProps & {
|
|
36
|
+
/** Минимум два цвета, для одного используйте `style.backgroundColor` у View */
|
|
37
|
+
colors: readonly [IColorValue, IColorValue, ...IColorValue[]];
|
|
38
|
+
/** Позиции остановок от 0 до 1 по возрастанию, той же длины, что и `colors` */
|
|
39
|
+
locations?: readonly [number, number, ...number[]] | null;
|
|
40
|
+
/** @default { x: 0.5, y: 0.0 } */
|
|
41
|
+
start?: ILinearGradientPoint | null;
|
|
42
|
+
/** @default { x: 0.5, y: 1.0 } */
|
|
43
|
+
end?: ILinearGradientPoint | null;
|
|
44
|
+
/**
|
|
45
|
+
* Дизеринг убирает полосы в градиенте, false может ускорить отрисовку
|
|
46
|
+
* @default true
|
|
47
|
+
* @platform android
|
|
48
|
+
*/
|
|
49
|
+
dither?: boolean;
|
|
50
|
+
style?: IStyleProp<IViewStyle>;
|
|
51
|
+
testID?: string;
|
|
52
|
+
nativeID?: string;
|
|
53
|
+
onLayout?: (event: ISymbioteEvent) => void;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Эти ключи разбираются здесь, остальное уходит на хост как есть
|
|
57
|
+
const GRADIENT_KEYS: ReadonlySet<string> = new Set<keyof ILinearGradientProps>([
|
|
58
|
+
'colors',
|
|
59
|
+
'locations',
|
|
60
|
+
'start',
|
|
61
|
+
'end',
|
|
62
|
+
'dither',
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
const ABSOLUTE_FILL = {
|
|
66
|
+
position: 'absolute',
|
|
67
|
+
left: 0,
|
|
68
|
+
right: 0,
|
|
69
|
+
top: 0,
|
|
70
|
+
bottom: 0,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export function linearGradientViewName(): string {
|
|
74
|
+
return expoViewManagerName(LINEAR_GRADIENT_MODULE_NAME);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Регистрирует view config в реестре RN, из него движок берёт события и процессоры пропсов
|
|
78
|
+
// Зовётся при рендере, а не при импорте: регистрация в побочном эффекте барреля теряется в release
|
|
79
|
+
export function ensureLinearGradientRegistered(): boolean {
|
|
80
|
+
return tryRegisterNativeView(() =>
|
|
81
|
+
requireNativeViewManager(LINEAR_GRADIENT_MODULE_NAME),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isNumber(value: unknown): value is number {
|
|
86
|
+
return typeof value === 'number';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function normalizePoint(
|
|
90
|
+
point: unknown,
|
|
91
|
+
): INativeLinearGradientPoint | undefined {
|
|
92
|
+
if (!point) return undefined;
|
|
93
|
+
if (Array.isArray(point)) {
|
|
94
|
+
const [x, y] = point;
|
|
95
|
+
if (point.length === 2 && isNumber(x) && isNumber(y)) return [x, y];
|
|
96
|
+
console.warn(
|
|
97
|
+
'start and end props for LinearGradient must be of the format [x,y] or {x, y}',
|
|
98
|
+
);
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
const x: unknown = Reflect.get(Object(point), 'x');
|
|
102
|
+
const y: unknown = Reflect.get(Object(point), 'y');
|
|
103
|
+
return isNumber(x) && isNumber(y) ? [x, y] : undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function resolveLocations(
|
|
107
|
+
colors: readonly unknown[],
|
|
108
|
+
locations: unknown,
|
|
109
|
+
): readonly number[] | undefined {
|
|
110
|
+
if (!Array.isArray(locations)) return undefined;
|
|
111
|
+
if (locations.length === colors.length) return locations;
|
|
112
|
+
console.warn(
|
|
113
|
+
'LinearGradient colors and locations props should be arrays of the same length',
|
|
114
|
+
);
|
|
115
|
+
return locations.slice(0, colors.length);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function radiusOr(value: unknown, fallback: number): number {
|
|
119
|
+
return isNumber(value) ? value : fallback;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Формат из `Path.addRoundRect`: по два значения на угол, начиная с верхнего левого
|
|
123
|
+
function borderRadiiOf(style: unknown): number[] {
|
|
124
|
+
const flat = flattenStyle(style) ?? {};
|
|
125
|
+
const base = radiusOr(flat.borderRadius, 0);
|
|
126
|
+
const topLeft = radiusOr(flat.borderTopLeftRadius, base);
|
|
127
|
+
const topRight = radiusOr(flat.borderTopRightRadius, base);
|
|
128
|
+
const bottomRight = radiusOr(flat.borderBottomRightRadius, base);
|
|
129
|
+
const bottomLeft = radiusOr(flat.borderBottomLeftRadius, base);
|
|
130
|
+
return [
|
|
131
|
+
topLeft,
|
|
132
|
+
topLeft,
|
|
133
|
+
topRight,
|
|
134
|
+
topRight,
|
|
135
|
+
bottomRight,
|
|
136
|
+
bottomRight,
|
|
137
|
+
bottomLeft,
|
|
138
|
+
bottomLeft,
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function withoutUndefined(
|
|
143
|
+
props: Record<string, unknown>,
|
|
144
|
+
): Record<string, unknown> {
|
|
145
|
+
return Object.fromEntries(
|
|
146
|
+
Object.entries(props).filter(([, value]) => value !== undefined),
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// `object`, а не тип пропсов: Vue и Angular отдают нетипизированный набор атрибутов
|
|
151
|
+
export function renderLinearGradient(props: object): IDescriptor {
|
|
152
|
+
const hostProps = Object.fromEntries(
|
|
153
|
+
Object.entries(props).filter(([key]) => !GRADIENT_KEYS.has(key)),
|
|
154
|
+
);
|
|
155
|
+
if (!ensureLinearGradientRegistered()) {
|
|
156
|
+
console.warn('LinearGradient is not available on this platform');
|
|
157
|
+
return el('view', hostProps);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const colors: unknown = Reflect.get(props, 'colors');
|
|
161
|
+
const colorList = Array.isArray(colors) ? colors : [];
|
|
162
|
+
const nativeProps = withoutUndefined({
|
|
163
|
+
colors: colorList.map(color => processColor(color)),
|
|
164
|
+
locations: resolveLocations(colorList, Reflect.get(props, 'locations')),
|
|
165
|
+
startPoint: normalizePoint(Reflect.get(props, 'start')),
|
|
166
|
+
endPoint: normalizePoint(Reflect.get(props, 'end')),
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (!Platform.select({ android: true, default: false })) {
|
|
170
|
+
return el(linearGradientViewName(), { ...hostProps, ...nativeProps });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Нативный градиент заполняет View и сам скругляет углы, т.к. RN не обрезает по радиусу
|
|
174
|
+
const native = el(
|
|
175
|
+
linearGradientViewName(),
|
|
176
|
+
withoutUndefined({
|
|
177
|
+
...nativeProps,
|
|
178
|
+
style: ABSOLUTE_FILL,
|
|
179
|
+
borderRadii: borderRadiiOf(styleOfProps(props)),
|
|
180
|
+
dither: Reflect.get(props, 'dither'),
|
|
181
|
+
}),
|
|
182
|
+
);
|
|
183
|
+
return el('view', hostProps, [native]);
|
|
184
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @symbiote-native/linear-gradient/react: компонент `LinearGradient` поверх общего ядра
|
|
2
|
+
|
|
3
|
+
export { LinearGradient } from './linear-gradient';
|
|
4
|
+
export type { ILinearGradientProps } from './linear-gradient';
|
|
5
|
+
export {
|
|
6
|
+
LINEAR_GRADIENT_MODULE_NAME,
|
|
7
|
+
linearGradientViewName,
|
|
8
|
+
type ILinearGradientPoint,
|
|
9
|
+
type INativeLinearGradientPoint,
|
|
10
|
+
} from '../core';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import { descriptorToReactWithChildren } from '@symbiote-native/react';
|
|
3
|
+
import type { IViewProps } from '@symbiote-native/react';
|
|
4
|
+
import { renderLinearGradient } from '../core/linear-gradient';
|
|
5
|
+
import type { ILinearGradientProps as ILinearGradientBaseProps } from '../core/linear-gradient';
|
|
6
|
+
|
|
7
|
+
// Поверхность View как у `ViewProps` в upstream, дети и `className` свои у React
|
|
8
|
+
export type ILinearGradientProps = ILinearGradientBaseProps &
|
|
9
|
+
Omit<IViewProps, keyof ILinearGradientBaseProps | 'children'> & {
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
className?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** React twin of `expo-linear-gradient`'s `LinearGradient`, children paint over the gradient */
|
|
15
|
+
export function LinearGradient(props: ILinearGradientProps): ReactElement {
|
|
16
|
+
const { children, ...rest } = props;
|
|
17
|
+
return descriptorToReactWithChildren(renderLinearGradient(rest), children);
|
|
18
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @symbiote-native/linear-gradient/solid: компонент `LinearGradient` поверх общего ядра
|
|
2
|
+
|
|
3
|
+
export { LinearGradient } from './linear-gradient';
|
|
4
|
+
export type { ILinearGradientProps } from './linear-gradient';
|
|
5
|
+
export {
|
|
6
|
+
LINEAR_GRADIENT_MODULE_NAME,
|
|
7
|
+
linearGradientViewName,
|
|
8
|
+
type ILinearGradientPoint,
|
|
9
|
+
type INativeLinearGradientPoint,
|
|
10
|
+
} from '../core';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js';
|
|
2
|
+
import { defineDescriptorComponent } from '@symbiote-native/solid';
|
|
3
|
+
import type { IViewProps } from '@symbiote-native/solid';
|
|
4
|
+
import type { IClassNameValue } from '@symbiote-native/engine';
|
|
5
|
+
import { renderLinearGradient } from '../core/linear-gradient';
|
|
6
|
+
import type { ILinearGradientProps as ILinearGradientBaseProps } from '../core/linear-gradient';
|
|
7
|
+
|
|
8
|
+
// Поверхность View как у `ViewProps` в upstream, дети и `class` свои у Solid
|
|
9
|
+
export type ILinearGradientProps = ILinearGradientBaseProps &
|
|
10
|
+
Omit<IViewProps, keyof ILinearGradientBaseProps | 'children' | 'ref'> & {
|
|
11
|
+
children?: JSX.Element;
|
|
12
|
+
class?: IClassNameValue;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Solid twin of `expo-linear-gradient`'s `LinearGradient`, children paint over the gradient */
|
|
16
|
+
export const LinearGradient =
|
|
17
|
+
defineDescriptorComponent<ILinearGradientProps>(renderLinearGradient);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @symbiote-native/linear-gradient/svelte: компонент `LinearGradient` поверх общего ядра
|
|
2
|
+
|
|
3
|
+
export { default as LinearGradient } from './linear-gradient.svelte';
|
|
4
|
+
export type { ILinearGradientProps } from './linear-gradient-props';
|
|
5
|
+
export {
|
|
6
|
+
LINEAR_GRADIENT_MODULE_NAME,
|
|
7
|
+
linearGradientViewName,
|
|
8
|
+
type ILinearGradientPoint,
|
|
9
|
+
type INativeLinearGradientPoint,
|
|
10
|
+
} from '../core';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { IViewProps } from '@symbiote-native/svelte';
|
|
3
|
+
import type { ILinearGradientProps as ILinearGradientBaseProps } from '../core/linear-gradient';
|
|
4
|
+
|
|
5
|
+
// Поверхность View как у `ViewProps` в upstream, дети идут сниппетом
|
|
6
|
+
export type ILinearGradientProps = ILinearGradientBaseProps &
|
|
7
|
+
Omit<IViewProps, keyof ILinearGradientBaseProps | 'children'> & {
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import DescriptorHost from '@symbiote-native/svelte/descriptor-host';
|
|
3
|
+
import { renderLinearGradient } from '../core/linear-gradient';
|
|
4
|
+
import type { ILinearGradientProps } from './linear-gradient-props';
|
|
5
|
+
|
|
6
|
+
const { children, ...rest }: ILinearGradientProps = $props();
|
|
7
|
+
const descriptor = $derived(renderLinearGradient({ ...rest }));
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<DescriptorHost {descriptor} {children} />
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Pulls in svelte's ambient global declarations ($state/$effect/...) for this package's tsc
|
|
2
|
+
// program. adapters/svelte gets these for free because render.ts does a real value import from
|
|
3
|
+
// 'svelte' (any file in a program importing a module loads its ambient globals for the whole
|
|
4
|
+
// program); this package has no such import, so a triple-slash reference does the same job
|
|
5
|
+
// explicitly rather than relying on an incidental side-effect.
|
|
6
|
+
/// <reference types="svelte" />
|
package/src/vue/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @symbiote-native/linear-gradient/vue: компонент `LinearGradient` поверх общего ядра
|
|
2
|
+
|
|
3
|
+
export { LinearGradient } from './linear-gradient';
|
|
4
|
+
export type { ILinearGradientProps } from './linear-gradient';
|
|
5
|
+
export {
|
|
6
|
+
LINEAR_GRADIENT_MODULE_NAME,
|
|
7
|
+
linearGradientViewName,
|
|
8
|
+
type ILinearGradientPoint,
|
|
9
|
+
type INativeLinearGradientPoint,
|
|
10
|
+
} from '../core';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineComponent, type VNode } from '@vue/runtime-core';
|
|
2
|
+
import { descriptorToVue, normalizeVueAttrs } from '@symbiote-native/vue';
|
|
3
|
+
import type { IViewProps } from '@symbiote-native/vue';
|
|
4
|
+
import { renderLinearGradient } from '../core/linear-gradient';
|
|
5
|
+
import type { ILinearGradientProps as ILinearGradientBaseProps } from '../core/linear-gradient';
|
|
6
|
+
|
|
7
|
+
// Поверхность View как у `ViewProps` в upstream, дети идут слотом по умолчанию
|
|
8
|
+
export type ILinearGradientProps = ILinearGradientBaseProps &
|
|
9
|
+
Omit<IViewProps, keyof ILinearGradientBaseProps>;
|
|
10
|
+
|
|
11
|
+
/** Vue twin of `expo-linear-gradient`'s `LinearGradient`, the default slot paints over it */
|
|
12
|
+
export const LinearGradient = defineComponent({
|
|
13
|
+
name: 'LinearGradient',
|
|
14
|
+
// Все атрибуты это пропсы нативного view, на обёртку ничего не должно просочиться
|
|
15
|
+
inheritAttrs: false,
|
|
16
|
+
setup(_props, { attrs, slots }) {
|
|
17
|
+
return (): VNode => {
|
|
18
|
+
const descriptor = renderLinearGradient(normalizeVueAttrs(attrs));
|
|
19
|
+
// Слот приложения идёт в корень после собственных детей дескриптора
|
|
20
|
+
return descriptorToVue(descriptor, slots.default?.() ?? []);
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
});
|