@pyreon/elements 0.24.4 → 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.
Files changed (70) hide show
  1. package/package.json +10 -12
  2. package/src/Element/component.tsx +0 -315
  3. package/src/Element/constants.ts +0 -96
  4. package/src/Element/index.ts +0 -6
  5. package/src/Element/types.ts +0 -168
  6. package/src/Element/utils.ts +0 -15
  7. package/src/List/component.tsx +0 -105
  8. package/src/List/index.ts +0 -5
  9. package/src/Overlay/component.tsx +0 -140
  10. package/src/Overlay/context.tsx +0 -36
  11. package/src/Overlay/index.ts +0 -7
  12. package/src/Overlay/positioning.ts +0 -191
  13. package/src/Overlay/useOverlay.tsx +0 -461
  14. package/src/Portal/component.tsx +0 -54
  15. package/src/Portal/index.ts +0 -5
  16. package/src/Text/component.tsx +0 -67
  17. package/src/Text/index.ts +0 -5
  18. package/src/Text/styled.ts +0 -30
  19. package/src/Util/component.tsx +0 -43
  20. package/src/Util/index.ts +0 -5
  21. package/src/__tests__/Content.test.tsx +0 -123
  22. package/src/__tests__/Element-slot-reactivity.browser.test.tsx +0 -152
  23. package/src/__tests__/Element.test.ts +0 -819
  24. package/src/__tests__/Iterator.test.ts +0 -492
  25. package/src/__tests__/Iterator.types.test.ts +0 -237
  26. package/src/__tests__/List.test.ts +0 -199
  27. package/src/__tests__/Overlay.test.ts +0 -492
  28. package/src/__tests__/Portal.test.ts +0 -156
  29. package/src/__tests__/Text.test.ts +0 -274
  30. package/src/__tests__/Util.test.ts +0 -63
  31. package/src/__tests__/Wrapper-innerhtml.test.tsx +0 -178
  32. package/src/__tests__/Wrapper.test.tsx +0 -196
  33. package/src/__tests__/elements.browser.test.tsx +0 -132
  34. package/src/__tests__/equalBeforeAfter.test.ts +0 -122
  35. package/src/__tests__/helpers.test.ts +0 -65
  36. package/src/__tests__/integration.test.tsx +0 -118
  37. package/src/__tests__/internElementBundle.test.ts +0 -102
  38. package/src/__tests__/iterator-function-children.test.tsx +0 -120
  39. package/src/__tests__/native-markers.test.ts +0 -13
  40. package/src/__tests__/overlayContext.test.tsx +0 -78
  41. package/src/__tests__/perf-stress.browser.test.tsx +0 -119
  42. package/src/__tests__/positioning.test.ts +0 -90
  43. package/src/__tests__/responsiveProps.test.ts +0 -328
  44. package/src/__tests__/slot-component-reference.test.tsx +0 -157
  45. package/src/__tests__/useOverlay.test.ts +0 -1336
  46. package/src/__tests__/utils.test.ts +0 -69
  47. package/src/__tests__/wrapper-block-cascade.test.ts +0 -121
  48. package/src/constants.ts +0 -1
  49. package/src/env.d.ts +0 -6
  50. package/src/helpers/Content/component.tsx +0 -75
  51. package/src/helpers/Content/index.ts +0 -3
  52. package/src/helpers/Content/styled.ts +0 -105
  53. package/src/helpers/Content/types.ts +0 -49
  54. package/src/helpers/Iterator/component.tsx +0 -316
  55. package/src/helpers/Iterator/index.ts +0 -30
  56. package/src/helpers/Iterator/types.ts +0 -138
  57. package/src/helpers/Wrapper/component.tsx +0 -180
  58. package/src/helpers/Wrapper/constants.ts +0 -10
  59. package/src/helpers/Wrapper/index.ts +0 -3
  60. package/src/helpers/Wrapper/styled.ts +0 -64
  61. package/src/helpers/Wrapper/types.ts +0 -56
  62. package/src/helpers/Wrapper/utils.ts +0 -7
  63. package/src/helpers/index.ts +0 -4
  64. package/src/helpers/internElementBundle.ts +0 -37
  65. package/src/helpers/isPyreonComponent.ts +0 -46
  66. package/src/index.ts +0 -42
  67. package/src/manifest.ts +0 -190
  68. package/src/tests/manifest-snapshot.test.ts +0 -45
  69. package/src/types.ts +0 -112
  70. package/src/utils.ts +0 -5
@@ -1,69 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { getShouldBeEmpty, isInlineElement } from '../Element/utils'
3
- import { isWebFixNeeded } from '../helpers/Wrapper/utils'
4
-
5
- describe('isInlineElement', () => {
6
- it('returns true for inline elements', () => {
7
- expect(isInlineElement('span')).toBe(true)
8
- expect(isInlineElement('a')).toBe(true)
9
- expect(isInlineElement('button')).toBe(true)
10
- expect(isInlineElement('input')).toBe(true)
11
- expect(isInlineElement('label')).toBe(true)
12
- expect(isInlineElement('strong')).toBe(true)
13
- expect(isInlineElement('em')).toBe(true)
14
- expect(isInlineElement('img')).toBe(true)
15
- })
16
-
17
- it('returns false for block elements', () => {
18
- expect(isInlineElement('div')).toBe(false)
19
- expect(isInlineElement('p')).toBe(false)
20
- expect(isInlineElement('section')).toBe(false)
21
- expect(isInlineElement('header')).toBe(false)
22
- })
23
-
24
- it('returns false for undefined', () => {
25
- expect(isInlineElement(undefined)).toBe(false)
26
- })
27
-
28
- it('returns false for empty string', () => {
29
- expect(isInlineElement('')).toBe(false)
30
- })
31
- })
32
-
33
- describe('getShouldBeEmpty', () => {
34
- it('returns true for void elements', () => {
35
- expect(getShouldBeEmpty('br')).toBe(true)
36
- expect(getShouldBeEmpty('img')).toBe(true)
37
- expect(getShouldBeEmpty('input')).toBe(true)
38
- expect(getShouldBeEmpty('hr')).toBe(true)
39
- expect(getShouldBeEmpty('embed')).toBe(true)
40
- })
41
-
42
- it('returns false for non-void elements', () => {
43
- expect(getShouldBeEmpty('div')).toBe(false)
44
- expect(getShouldBeEmpty('span')).toBe(false)
45
- expect(getShouldBeEmpty('p')).toBe(false)
46
- })
47
-
48
- it('returns false for undefined', () => {
49
- expect(getShouldBeEmpty(undefined)).toBe(false)
50
- })
51
- })
52
-
53
- describe('isWebFixNeeded', () => {
54
- it('returns true for button, fieldset, legend', () => {
55
- expect(isWebFixNeeded('button')).toBe(true)
56
- expect(isWebFixNeeded('fieldset')).toBe(true)
57
- expect(isWebFixNeeded('legend')).toBe(true)
58
- })
59
-
60
- it('returns false for other elements', () => {
61
- expect(isWebFixNeeded('div')).toBe(false)
62
- expect(isWebFixNeeded('span')).toBe(false)
63
- expect(isWebFixNeeded('input')).toBe(false)
64
- })
65
-
66
- it('returns false for undefined', () => {
67
- expect(isWebFixNeeded(undefined)).toBe(false)
68
- })
69
- })
@@ -1,121 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { styles } from '../helpers/Wrapper/styled'
3
-
4
- /**
5
- * Regression test for the responsive `block` cascade bug (mirrors vitus-labs's
6
- * "couple of fixes" PR #121).
7
- *
8
- * Scenario: a responsive theme like `block: [true, false, true]` runs the
9
- * styles callback once per breakpoint with a single-value `t.block`. The bug
10
- * was that `align-self`, `flex`/`width` etc. were emitted ONLY when
11
- * `t.block` was truthy — so the breakpoint where `t.block` is false emitted
12
- * nothing, leaving the previous breakpoint's `align-self: stretch` cascading
13
- * through the mobile-first @media query.
14
- *
15
- * Fix: always emit a value for these properties (truthy → stretch/100%,
16
- * falsy → auto/auto). The mobile-first @media cascade then resets cleanly
17
- * when `block` flips false at a later breakpoint.
18
- *
19
- * The styles callback is called per-breakpoint with the per-breakpoint theme
20
- * already resolved to a single value — so testing it directly with two
21
- * scalar themes is enough to lock in the always-emit contract.
22
- */
23
-
24
- const identityCss = (strings: TemplateStringsArray, ...vals: unknown[]) => {
25
- let r = ''
26
- for (let i = 0; i < strings.length; i++) {
27
- r += strings[i]
28
- if (i < vals.length) {
29
- const v = vals[i]
30
- // Mirror styled-components / styler interpolation: drop falsy
31
- // interpolations, stringify the rest. CSSResult instances (from the
32
- // alignContent / extendCss helpers) coerce via their toString.
33
- if (v === false || v == null) continue
34
- r += String(v)
35
- }
36
- }
37
- return r
38
- }
39
-
40
- const renderAt = (theme: Record<string, unknown>): string =>
41
- String(styles({ theme, css: identityCss }))
42
-
43
- describe('Wrapper styles — responsive block cascade reset', () => {
44
- it('emits stretch/100%/flex when block is true', () => {
45
- const out = renderAt({
46
- block: true,
47
- direction: 'inline',
48
- alignX: 'left',
49
- alignY: 'center',
50
- })
51
- expect(out).toContain('align-self: stretch')
52
- expect(out).toContain('width: 100%')
53
- expect(out).toContain('display: flex')
54
- })
55
-
56
- it('emits auto/auto/inline-flex reset when block is false (key fix)', () => {
57
- const out = renderAt({
58
- block: false,
59
- direction: 'inline',
60
- alignX: 'left',
61
- alignY: 'center',
62
- })
63
- // The fix: these properties MUST be emitted with reset values so the
64
- // mobile-first @media cascade doesn't leak `align-self: stretch` from a
65
- // smaller breakpoint where block was true.
66
- expect(out).toContain('align-self: auto')
67
- expect(out).toContain('width: auto')
68
- expect(out).toContain('display: inline-flex')
69
- })
70
-
71
- it('emits height: 100% when alignY is "block", auto otherwise', () => {
72
- const blockY = renderAt({
73
- block: false,
74
- direction: 'inline',
75
- alignX: 'left',
76
- alignY: 'block',
77
- })
78
- expect(blockY).toContain('height: 100%')
79
-
80
- const nonBlockY = renderAt({
81
- block: false,
82
- direction: 'inline',
83
- alignX: 'left',
84
- alignY: 'center',
85
- })
86
- expect(nonBlockY).toContain('height: auto')
87
- })
88
-
89
- it('does not emit display when childFix is set (parent split)', () => {
90
- const out = renderAt({
91
- block: true,
92
- childFix: true,
93
- direction: 'inline',
94
- alignX: 'left',
95
- alignY: 'center',
96
- })
97
- // childFix branch handles its own display rules outside the responsive
98
- // styles callback.
99
- expect(out).not.toContain('display: flex;')
100
- expect(out).not.toContain('display: inline-flex;')
101
- })
102
-
103
- it('emits parentFix flex-direction: column only when parentFix is set', () => {
104
- const withParentFix = renderAt({
105
- block: true,
106
- parentFix: true,
107
- direction: 'inline',
108
- alignX: 'left',
109
- alignY: 'center',
110
- })
111
- expect(withParentFix).toContain('flex-direction: column')
112
-
113
- const withoutParentFix = renderAt({
114
- block: true,
115
- direction: 'inline',
116
- alignX: 'left',
117
- alignY: 'center',
118
- })
119
- expect(withoutParentFix).not.toContain('flex-direction: column')
120
- })
121
- })
package/src/constants.ts DELETED
@@ -1 +0,0 @@
1
- export const PKG_NAME = '@pyreon/elements' as const
package/src/env.d.ts DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * Minimal process type — just enough for `process.env.NODE_ENV` checks.
3
- * Avoids requiring @types/node in consumers that import pyreon source
4
- * via the `"bun"` export condition.
5
- */
6
- declare var process: { env: { NODE_ENV?: string } }
@@ -1,75 +0,0 @@
1
- /**
2
- * Content area used inside Element to render one of the three
3
- * layout slots (before, content, after). Passes alignment, direction,
4
- * gap, and equalCols styling props to the underlying styled component.
5
- * Adds a `data-pyr-element` attribute in development for debugging.
6
- *
7
- * Children are rendered via core `render()`, with function-valued
8
- * children unwrapped inside a reactive accessor so the compound-layout
9
- * paths in `Element` keep `content={() => <X />}` reactivity intact
10
- * (mirrors the `resolveSlot` helper in `Element/component.tsx`).
11
- */
12
- import { h, splitProps } from '@pyreon/core'
13
- import type { ComponentFn, VNodeChildAtom } from '@pyreon/core'
14
- import { render } from '@pyreon/ui-core'
15
- import { IS_DEVELOPMENT } from '../../utils'
16
- import { isPyreonComponent } from '../isPyreonComponent'
17
- import Styled from './styled'
18
- import type { Props } from './types'
19
-
20
- // Return type is the RESOLVED atom — see the matching helper in
21
- // Element/component.tsx for the rationale (keeps `() => resolveSlot(...)`
22
- // a valid VNodeChildAccessor at the JSX child position).
23
- //
24
- // Component vs accessor discriminator — see `isPyreonComponent` JSDoc.
25
- // Without this, `beforeContent={Component}` shorthand crashes downstream
26
- // in rocketstyle's `removeUndefinedProps(undefined)`.
27
- const resolveSlot = (value: unknown): VNodeChildAtom | VNodeChildAtom[] => {
28
- if (typeof value === 'function') {
29
- if (isPyreonComponent(value)) {
30
- return h(value as ComponentFn, null) as VNodeChildAtom
31
- }
32
- return (value as () => VNodeChildAtom | VNodeChildAtom[])()
33
- }
34
- return render(value as Parameters<typeof render>[0]) as VNodeChildAtom | VNodeChildAtom[]
35
- }
36
-
37
- const Component = (props: Partial<Props>) => {
38
- const [own, rest] = splitProps(props, [
39
- 'contentType',
40
- 'tag',
41
- 'parentDirection',
42
- 'direction',
43
- 'alignX',
44
- 'alignY',
45
- 'equalCols',
46
- 'gap',
47
- 'extendCss',
48
- 'children',
49
- ])
50
-
51
- const debugProps = IS_DEVELOPMENT
52
- ? {
53
- 'data-pyr-element': own.contentType,
54
- }
55
- : {}
56
-
57
- const stylingProps = {
58
- contentType: own.contentType,
59
- parentDirection: own.parentDirection,
60
- direction: own.direction,
61
- alignX: own.alignX,
62
- alignY: own.alignY,
63
- equalCols: own.equalCols,
64
- gap: own.gap,
65
- extraStyles: own.extendCss,
66
- }
67
-
68
- return (
69
- <Styled as={own.tag} $contentType={own.contentType} $element={stylingProps} {...debugProps} {...rest}>
70
- {() => resolveSlot(own.children)}
71
- </Styled>
72
- )
73
- }
74
-
75
- export default Component
@@ -1,3 +0,0 @@
1
- import component from './component'
2
-
3
- export default component
@@ -1,105 +0,0 @@
1
- /**
2
- * Styled component for content areas (before/content/after). Applies
3
- * responsive flex alignment, gap spacing between slots based on parent
4
- * direction (margin-right for inline, margin-bottom for rows), and
5
- * equalCols flex distribution. The "content" slot gets `flex: 1` to
6
- * fill remaining space between before and after.
7
- */
8
- import { config } from '@pyreon/ui-core'
9
- import { alignContent, extendCss, makeItResponsive, value } from '@pyreon/unistyle'
10
- import type { ResponsiveStylesCallback } from '../../types'
11
- import type { StyledProps, ThemeProps } from './types'
12
-
13
- const { styled, css, component } = config
14
-
15
- const equalColsCSS = `
16
- flex: 1;
17
- `
18
-
19
- const typeContentCSS = `
20
- flex: 1;
21
- `
22
-
23
- // --------------------------------------------------------
24
- // calculate spacing between before / content / after
25
- // --------------------------------------------------------
26
- const gapDimensions = {
27
- inline: {
28
- before: 'margin-right',
29
- after: 'margin-left',
30
- },
31
- reverseInline: {
32
- before: 'margin-right',
33
- after: 'margin-left',
34
- },
35
- rows: {
36
- before: 'margin-bottom',
37
- after: 'margin-top',
38
- },
39
- reverseRows: {
40
- before: 'margin-bottom',
41
- after: 'margin-top',
42
- },
43
- } as const
44
-
45
- const calculateGap = ({
46
- direction,
47
- type,
48
- value: gapValue,
49
- }: {
50
- direction: keyof typeof gapDimensions
51
- type: ThemeProps['contentType']
52
- value: string | number | null | undefined
53
- }) => {
54
- if (!direction || !type || type === 'content') return undefined
55
-
56
- const finalStyles = `${gapDimensions[direction][type]}: ${gapValue};`
57
-
58
- return finalStyles
59
- }
60
-
61
- // --------------------------------------------------------
62
- // calculations of styles to be rendered
63
- // --------------------------------------------------------
64
- const styles: ResponsiveStylesCallback = ({ css: cssFn, theme: t, rootSize }) => cssFn`
65
- ${alignContent({
66
- direction: t.direction,
67
- alignX: t.alignX,
68
- alignY: t.alignY,
69
- })};
70
-
71
- ${t.equalCols && equalColsCSS};
72
-
73
- ${
74
- t.gap &&
75
- t.contentType &&
76
- calculateGap({
77
- direction: t.parentDirection,
78
- type: t.contentType,
79
- value: value(t.gap, rootSize),
80
- })
81
- };
82
-
83
- ${t.extraStyles && extendCss(t.extraStyles as Parameters<typeof extendCss>[0])};
84
- `
85
-
86
- const platformCSS = `box-sizing: border-box;`
87
-
88
- const StyledComponent = styled(component, { layer: 'elements' })`
89
- ${platformCSS};
90
-
91
- display: flex;
92
- align-self: stretch;
93
- flex-wrap: wrap;
94
-
95
- ${(({ $contentType }: StyledProps) => $contentType === 'content' && typeContentCSS) as any};
96
-
97
- ${makeItResponsive({
98
- key: '$element',
99
- styles,
100
- css,
101
- normalize: true,
102
- })};
103
- `
104
-
105
- export default StyledComponent
@@ -1,49 +0,0 @@
1
- import type { HTMLTags } from '@pyreon/ui-core'
2
- import type {
3
- AlignX,
4
- AlignY,
5
- Content,
6
- ContentAlignX,
7
- ContentAlignY,
8
- ContentBoolean,
9
- ContentDirection,
10
- ContentSimpleValue,
11
- Css,
12
- Direction,
13
- ExtendCss,
14
- Responsive,
15
- ResponsiveBoolType,
16
- } from '../../types'
17
-
18
- export interface Props {
19
- parentDirection: Direction | undefined
20
- gap: Responsive | undefined
21
- contentType: 'before' | 'content' | 'after' | undefined
22
- children: Content
23
- tag: HTMLTags | undefined
24
- direction: Direction | undefined
25
- alignX: AlignX | undefined
26
- alignY: AlignY | undefined
27
- equalCols: ResponsiveBoolType | undefined
28
- extendCss: ExtendCss | undefined
29
- }
30
-
31
- export interface StyledProps {
32
- $element: Pick<
33
- Props,
34
- 'contentType' | 'parentDirection' | 'direction' | 'alignX' | 'alignY' | 'equalCols' | 'gap'
35
- > & {
36
- extraStyles: Props['extendCss']
37
- }
38
- $contentType: Props['contentType']
39
- }
40
-
41
- export type ThemeProps = Pick<Props, 'contentType'> & {
42
- parentDirection: ContentDirection
43
- direction: ContentDirection
44
- alignX: ContentAlignX
45
- alignY: ContentAlignY
46
- equalCols?: ContentBoolean
47
- gap?: ContentSimpleValue
48
- extraStyles?: Css
49
- }