@pyreon/ui-core 0.24.5 → 0.24.6
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/package.json +7 -9
- package/src/PyreonUI.tsx +0 -227
- package/src/__tests__/PyreonUI-inheritance.test.tsx +0 -157
- package/src/__tests__/PyreonUI.test.tsx +0 -194
- package/src/__tests__/compose.test.ts +0 -32
- package/src/__tests__/config.test.ts +0 -102
- package/src/__tests__/context.test.tsx +0 -71
- package/src/__tests__/hoistNonReactStatics.test.tsx +0 -166
- package/src/__tests__/isEmpty.test.ts +0 -53
- package/src/__tests__/isEqual.test.ts +0 -114
- package/src/__tests__/manifest-snapshot.test.ts +0 -27
- package/src/__tests__/native-markers.test.ts +0 -13
- package/src/__tests__/render.test.tsx +0 -72
- package/src/__tests__/useStableValue.test.ts +0 -118
- package/src/__tests__/utils.test.ts +0 -537
- package/src/compose.ts +0 -11
- package/src/config.ts +0 -57
- package/src/context.tsx +0 -80
- package/src/hoistNonReactStatics.ts +0 -59
- package/src/html/htmlElementAttrs.ts +0 -106
- package/src/html/htmlTags.ts +0 -151
- package/src/html/index.ts +0 -11
- package/src/index.ts +0 -57
- package/src/isEmpty.ts +0 -20
- package/src/isEqual.ts +0 -27
- package/src/manifest.ts +0 -104
- package/src/render.tsx +0 -50
- package/src/types.ts +0 -5
- package/src/useStableValue.ts +0 -21
- package/src/utils.ts +0 -187
package/src/render.tsx
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { ComponentFn, Props, VNodeChild } from '@pyreon/core'
|
|
2
|
-
import { h } from '@pyreon/core'
|
|
3
|
-
|
|
4
|
-
type RenderProps<T extends Record<string, unknown> | undefined> = (props: Partial<T>) => VNodeChild
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Flexible element renderer that handles multiple content types:
|
|
8
|
-
* - Primitives (string, number) — returned as-is
|
|
9
|
-
* - Arrays — returned as-is
|
|
10
|
-
* - Component functions — created via h()
|
|
11
|
-
* - VNode objects — returned as-is (with props merged if provided)
|
|
12
|
-
* - Render props (functions) — called with attachProps
|
|
13
|
-
* - Falsy values — return null
|
|
14
|
-
*/
|
|
15
|
-
export type Render = <T extends Record<string, any> | undefined>(
|
|
16
|
-
content?: ComponentFn | string | VNodeChild | VNodeChild[] | RenderProps<T>,
|
|
17
|
-
attachProps?: T,
|
|
18
|
-
) => VNodeChild
|
|
19
|
-
|
|
20
|
-
const render: Render = (content, attachProps) => {
|
|
21
|
-
if (!content) return null
|
|
22
|
-
|
|
23
|
-
const t = typeof content
|
|
24
|
-
if (t === 'string' || t === 'number' || t === 'boolean' || t === 'bigint') {
|
|
25
|
-
return content as VNodeChild
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (Array.isArray(content)) {
|
|
29
|
-
return content as VNodeChild
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (typeof content === 'function') {
|
|
33
|
-
// Extract key from props — it's a VNode concept, not a component prop.
|
|
34
|
-
// Passing key inside props causes JSX runtime warnings.
|
|
35
|
-
if (attachProps && 'key' in attachProps) {
|
|
36
|
-
const { key: _key, ...rest } = attachProps
|
|
37
|
-
return h(content as string | ComponentFn, rest as Props)
|
|
38
|
-
}
|
|
39
|
-
return h(content as string | ComponentFn, (attachProps ?? {}) as Props)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// VNode object — return directly
|
|
43
|
-
if (typeof content === 'object') {
|
|
44
|
-
return content as VNodeChild
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return content as VNodeChild
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export default render
|
package/src/types.ts
DELETED
package/src/useStableValue.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { signal } from '@pyreon/reactivity'
|
|
2
|
-
import isEqual from './isEqual'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Returns a referentially stable version of `value`. The returned reference
|
|
6
|
-
* only changes when the value is no longer deeply equal to the previous one.
|
|
7
|
-
*
|
|
8
|
-
* Pyreon equivalent of the React useStableValue hook — uses a signal
|
|
9
|
-
* internally to hold the stable reference.
|
|
10
|
-
*/
|
|
11
|
-
const useStableValue = <T>(value: T): T => {
|
|
12
|
-
const ref = signal(value)
|
|
13
|
-
|
|
14
|
-
if (!isEqual(ref.peek(), value)) {
|
|
15
|
-
ref.set(value)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return ref.peek()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default useStableValue
|
package/src/utils.ts
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns a copy of `obj` without the specified keys.
|
|
3
|
-
*
|
|
4
|
-
* Accepts either an array of keys (builds a Set internally) or a
|
|
5
|
-
* pre-built `Set<string>` for hot paths where the same key list is
|
|
6
|
-
* reused across many calls (avoids per-call Set allocation).
|
|
7
|
-
*
|
|
8
|
-
* Copies own property DESCRIPTORS (not values) so that getter-shaped
|
|
9
|
-
* properties — produced by `makeReactiveProps` in `@pyreon/core` for
|
|
10
|
-
* compiler-emitted `<Comp prop={signal()}>` — survive the copy with
|
|
11
|
-
* their reactive subscription intact. For data properties the
|
|
12
|
-
* behaviour is identical to value-copying.
|
|
13
|
-
*/
|
|
14
|
-
export const omit = <T extends Record<string, any>>(
|
|
15
|
-
obj: T | null | undefined,
|
|
16
|
-
keys?: readonly (string | keyof T)[] | Set<string>,
|
|
17
|
-
): Partial<T> => {
|
|
18
|
-
if (obj == null) return {} as Partial<T>
|
|
19
|
-
const descriptors = Object.getOwnPropertyDescriptors(obj)
|
|
20
|
-
if (!keys || (keys instanceof Set ? keys.size === 0 : keys.length === 0)) {
|
|
21
|
-
return Object.defineProperties({} as Partial<T>, descriptors)
|
|
22
|
-
}
|
|
23
|
-
const keysSet = keys instanceof Set ? keys : new Set(keys as readonly string[])
|
|
24
|
-
const result: Record<string, any> = {}
|
|
25
|
-
for (const key of Object.keys(descriptors)) {
|
|
26
|
-
if (!keysSet.has(key)) {
|
|
27
|
-
Object.defineProperty(result, key, descriptors[key]!)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return result as Partial<T>
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Returns a copy of `obj` containing only the specified keys.
|
|
35
|
-
*
|
|
36
|
-
* See `omit` above — same descriptor-preserving semantics: getter-
|
|
37
|
-
* shaped properties survive the copy with reactive subscription
|
|
38
|
-
* intact. For data properties the behaviour is identical to
|
|
39
|
-
* value-copying.
|
|
40
|
-
*/
|
|
41
|
-
export const pick = <T extends Record<string, any>>(
|
|
42
|
-
obj: T | null | undefined,
|
|
43
|
-
keys?: readonly (string | keyof T)[],
|
|
44
|
-
): Partial<T> => {
|
|
45
|
-
if (obj == null) return {} as Partial<T>
|
|
46
|
-
if (!keys || keys.length === 0) {
|
|
47
|
-
return Object.defineProperties(
|
|
48
|
-
{} as Partial<T>,
|
|
49
|
-
Object.getOwnPropertyDescriptors(obj),
|
|
50
|
-
)
|
|
51
|
-
}
|
|
52
|
-
const result: Record<string, any> = {}
|
|
53
|
-
for (const key of keys) {
|
|
54
|
-
const k = key as string
|
|
55
|
-
const descriptor = Object.getOwnPropertyDescriptor(obj, k)
|
|
56
|
-
if (descriptor) {
|
|
57
|
-
Object.defineProperty(result, k, descriptor)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return result as Partial<T>
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const PATH_RE = /[^.[\]]+/g
|
|
64
|
-
|
|
65
|
-
const parsePath = (path: string | string[]): string[] => {
|
|
66
|
-
if (Array.isArray(path)) return path
|
|
67
|
-
const parts = path.match(PATH_RE)
|
|
68
|
-
return parts ?? []
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const isUnsafeKey = (key: string): boolean =>
|
|
72
|
-
key === '__proto__' || key === 'prototype' || key === 'constructor'
|
|
73
|
-
|
|
74
|
-
export const get = (obj: any, path: string | string[], defaultValue?: any): any => {
|
|
75
|
-
const keys = parsePath(path)
|
|
76
|
-
let result = obj
|
|
77
|
-
for (const key of keys) {
|
|
78
|
-
if (result == null || isUnsafeKey(key)) return defaultValue
|
|
79
|
-
result = result[key]
|
|
80
|
-
}
|
|
81
|
-
return result === undefined ? defaultValue : result
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export const set = (
|
|
85
|
-
obj: Record<string, any>,
|
|
86
|
-
path: string | string[],
|
|
87
|
-
value: any,
|
|
88
|
-
): Record<string, any> => {
|
|
89
|
-
const keys = parsePath(path)
|
|
90
|
-
let current = obj
|
|
91
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
92
|
-
const key = keys[i] as string
|
|
93
|
-
if (isUnsafeKey(key)) return obj
|
|
94
|
-
const nextKey = keys[i + 1] as string
|
|
95
|
-
if (isUnsafeKey(nextKey)) return obj
|
|
96
|
-
if (current[key] == null) {
|
|
97
|
-
current[key] = /^\d+$/.test(nextKey) ? [] : {}
|
|
98
|
-
}
|
|
99
|
-
current = current[key]
|
|
100
|
-
}
|
|
101
|
-
const lastKey = keys[keys.length - 1]
|
|
102
|
-
if (lastKey != null && !isUnsafeKey(lastKey)) {
|
|
103
|
-
current[lastKey] = value
|
|
104
|
-
}
|
|
105
|
-
return obj
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export const throttle = <T extends (...args: any[]) => any>(
|
|
109
|
-
fn: T,
|
|
110
|
-
wait: number = 0,
|
|
111
|
-
options?: { leading?: boolean; trailing?: boolean },
|
|
112
|
-
): T & { cancel: () => void } => {
|
|
113
|
-
const leading = options?.leading !== false
|
|
114
|
-
const trailing = options?.trailing !== false
|
|
115
|
-
let lastCallTime: number | undefined
|
|
116
|
-
let timeoutId: ReturnType<typeof setTimeout> | undefined
|
|
117
|
-
let lastArgs: any[] | undefined
|
|
118
|
-
|
|
119
|
-
const invoke = (args: any[]) => {
|
|
120
|
-
lastCallTime = Date.now()
|
|
121
|
-
fn(...args)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const startTrailingTimer = (args: any[], delay: number) => {
|
|
125
|
-
lastArgs = args
|
|
126
|
-
if (timeoutId !== undefined) return
|
|
127
|
-
timeoutId = setTimeout(() => {
|
|
128
|
-
timeoutId = undefined
|
|
129
|
-
if (lastArgs) {
|
|
130
|
-
invoke(lastArgs)
|
|
131
|
-
lastArgs = undefined
|
|
132
|
-
}
|
|
133
|
-
}, delay)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const throttled = (...args: any[]) => {
|
|
137
|
-
const now = Date.now()
|
|
138
|
-
const elapsed = lastCallTime === undefined ? wait : now - lastCallTime
|
|
139
|
-
if (elapsed >= wait) {
|
|
140
|
-
if (leading) {
|
|
141
|
-
invoke(args)
|
|
142
|
-
} else {
|
|
143
|
-
lastCallTime = now
|
|
144
|
-
if (trailing) startTrailingTimer(args, wait)
|
|
145
|
-
}
|
|
146
|
-
} else if (trailing) {
|
|
147
|
-
startTrailingTimer(args, wait - elapsed)
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
throttled.cancel = () => {
|
|
152
|
-
if (timeoutId !== undefined) {
|
|
153
|
-
clearTimeout(timeoutId)
|
|
154
|
-
timeoutId = undefined
|
|
155
|
-
}
|
|
156
|
-
lastArgs = undefined
|
|
157
|
-
lastCallTime = undefined
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return throttled as T & { cancel: () => void }
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const isPlainObject = (value: unknown): value is Record<string, any> =>
|
|
164
|
-
value !== null &&
|
|
165
|
-
typeof value === 'object' &&
|
|
166
|
-
!Array.isArray(value) &&
|
|
167
|
-
Object.getPrototypeOf(value) === Object.prototype
|
|
168
|
-
|
|
169
|
-
export const merge = <T extends Record<string, any>>(
|
|
170
|
-
target: T,
|
|
171
|
-
...sources: Record<string, any>[]
|
|
172
|
-
): T => {
|
|
173
|
-
for (const source of sources) {
|
|
174
|
-
if (source == null) continue
|
|
175
|
-
for (const key of Object.keys(source)) {
|
|
176
|
-
if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue
|
|
177
|
-
const targetVal = (target as Record<string, unknown>)[key]
|
|
178
|
-
const sourceVal = source[key]
|
|
179
|
-
if (isPlainObject(targetVal) && isPlainObject(sourceVal)) {
|
|
180
|
-
;(target as Record<string, unknown>)[key] = merge({ ...targetVal }, sourceVal)
|
|
181
|
-
} else {
|
|
182
|
-
;(target as Record<string, unknown>)[key] = sourceVal
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return target
|
|
187
|
-
}
|