@startupjs-ui/popover 0.1.3

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/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [0.1.3](https://github.com/startupjs/startupjs-ui/compare/v0.1.2...v0.1.3) (2025-12-29)
7
+
8
+ **Note:** Version bump only for package @startupjs-ui/popover
9
+
10
+
11
+
12
+
13
+
14
+ ## [0.1.2](https://github.com/startupjs/startupjs-ui/compare/v0.1.1...v0.1.2) (2025-12-29)
15
+
16
+
17
+ ### Features
18
+
19
+ * add mdx and docs packages. Refactor docs to get rid of any @startupjs/ui usage and use startupjs-ui instead ([703c926](https://github.com/startupjs/startupjs-ui/commit/703c92636efb0421ffd11783f692fc892b74018f))
20
+ * **popover:** refactor Popover component ([d43cda5](https://github.com/startupjs/startupjs-ui/commit/d43cda52d95f047bc916a7b42a388e3148513fc3))
package/README.mdx ADDED
@@ -0,0 +1,127 @@
1
+ import { useState } from 'react'
2
+ import { Sandbox } from '@startupjs-ui/docs'
3
+ import { faUserCircle } from '@fortawesome/free-solid-svg-icons'
4
+ import Popover, { _PropsJsonSchema as PopoverPropsJsonSchema } from './index'
5
+ import Icon from '@startupjs-ui/icon'
6
+ import Button from '@startupjs-ui/button'
7
+ import Div from '@startupjs-ui/div'
8
+ import Span from '@startupjs-ui/span'
9
+
10
+ # Popover
11
+
12
+ Pop-up window for displaying hidden content, linked in some way to a specific element on the page and becomes visible when you click on this.
13
+
14
+ ```jsx
15
+ import { Popover } from 'startupjs-ui'
16
+ ```
17
+
18
+ ## Initialization
19
+
20
+ Before use you need to configure [Portal](/docs/components/Portal)
21
+
22
+ ## Simple example
23
+
24
+ - `children` (ReactNode): anchor (visible part)
25
+ - `renderContent` (function: ReactNode): function returns hidden part
26
+
27
+ ```jsx example
28
+ const [visible, setVisible] = useState(false)
29
+
30
+ function renderContent () {
31
+ return (
32
+ <Div style={{ padding: 10 }}>
33
+ <Span>Content</Span>
34
+ </Div>
35
+ )
36
+ }
37
+
38
+ return (
39
+ <Popover
40
+ visible={visible}
41
+ onChange={setVisible}
42
+ renderContent={renderContent}
43
+ >
44
+ <Icon icon={faUserCircle} size='xl' />
45
+ </Popover>
46
+ )
47
+ ```
48
+
49
+ ## Position
50
+
51
+ - `position` (string - 'top', 'bottom', 'left', 'right'): position relative to the visible part
52
+ - `attachment` (string - 'start', 'center', 'end'): optional parameter for offset
53
+ - `placements` (array): what positions can be used for auto-fix
54
+
55
+ ```jsx example
56
+ const [visible, setVisible] = useState(false)
57
+
58
+ function renderContent () {
59
+ return (
60
+ <Div style={{ padding: 10 }}>
61
+ <Span>Content</Span>
62
+ </Div>
63
+ )
64
+ }
65
+
66
+ return (
67
+ <Popover
68
+ visible={visible}
69
+ onChange={setVisible}
70
+ position='top'
71
+ attachment='center'
72
+ renderContent={renderContent}
73
+ >
74
+ <Button>Open</Button>
75
+ </Popover>
76
+ )
77
+ ```
78
+
79
+ ## Stylization
80
+
81
+ - `style`: styles for the anchor wrapper
82
+ - `attachmentStyle`: styles for the popover container
83
+ - `overlayStyle`: dismiss overlay styles
84
+ - `arrow` (boolean): show an arrow
85
+ - `matchAnchorWidth` (boolean): the width of the popover is equal to the width of the anchor
86
+
87
+ ```jsx example
88
+ const [visible, setVisible] = useState(false)
89
+
90
+ function renderContent () {
91
+ return (
92
+ <Span style={{ color: '#fff' }}>Content</Span>
93
+ )
94
+ }
95
+
96
+ return (
97
+ <Popover
98
+ visible={visible}
99
+ onChange={setVisible}
100
+ arrow
101
+ matchAnchorWidth
102
+ attachment='center'
103
+ renderContent={renderContent}
104
+ attachmentStyle={{ backgroundColor: '#333', padding: 10 }}
105
+ >
106
+ <Button>Open</Button>
107
+ </Popover>
108
+ )
109
+ ```
110
+
111
+ ## Extra options
112
+
113
+ - `durationOpen` (number): animation time on opening
114
+ - `durationClose` (number): animation time on close
115
+
116
+ ## Sandbox
117
+
118
+ <Sandbox
119
+ Component={Popover}
120
+ propsJsonSchema={PopoverPropsJsonSchema}
121
+ props={{
122
+ visible: false,
123
+ onChange: () => {},
124
+ renderContent: () => <Div style={{ padding: 10 }}><Span>Content</Span></Div>,
125
+ children: <Span>Anchor</Span>
126
+ }}
127
+ />
@@ -0,0 +1,14 @@
1
+ .root
2
+ .overlay
3
+ position absolute
4
+ top 0
5
+ left 0
6
+ right 0
7
+ bottom 0
8
+
9
+ .attachment
10
+ background-color var(--color-bg-main-strong)
11
+ radius()
12
+ shadow(3)
13
+ overflow hidden
14
+
package/index.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ /* eslint-disable */
2
+ // DO NOT MODIFY THIS FILE - IT IS AUTOMATICALLY GENERATED ON COMMITS.
3
+
4
+ import { type ReactNode, type RefObject } from 'react';
5
+ import { type StyleProp, type ViewStyle } from 'react-native';
6
+ import { type AbstractPopoverProps } from '@startupjs-ui/abstract-popover';
7
+ import './index.cssx.styl';
8
+ export declare const _PropsJsonSchema: {};
9
+ export interface PopoverProps extends Omit<AbstractPopoverProps, 'anchorRef' | 'children' | 'style' | 'visible'> {
10
+ /** Ref to control popover programmatically */
11
+ ref?: RefObject<PopoverRef>;
12
+ /** Custom styles for the anchor wrapper */
13
+ style?: StyleProp<ViewStyle>;
14
+ /** Custom styles for the popover container */
15
+ attachmentStyle?: StyleProp<ViewStyle>;
16
+ /** Custom styles for the dismiss overlay */
17
+ overlayStyle?: StyleProp<ViewStyle>;
18
+ /** Controlled visibility flag */
19
+ visible?: boolean;
20
+ /** Two-way binding value controlling visibility */
21
+ $visible?: any;
22
+ /** Called when visibility should change */
23
+ onChange?: (visible: boolean) => void;
24
+ /** Anchor content */
25
+ children?: ReactNode;
26
+ /** Render function for popover content */
27
+ renderContent?: () => ReactNode;
28
+ }
29
+ export interface PopoverRef {
30
+ /** Open the popover */
31
+ open: () => void;
32
+ /** Close the popover */
33
+ close: () => void;
34
+ }
35
+ declare const _default: import("react").ComponentType<PopoverProps>;
36
+ export default _default;
package/index.tsx ADDED
@@ -0,0 +1,113 @@
1
+ import { useMemo, useRef, useCallback, useImperativeHandle, type ReactNode, type RefObject } from 'react'
2
+ import { View, TouchableWithoutFeedback, type StyleProp, type ViewStyle } from 'react-native'
3
+ import { pug, observer, useBind, $ } from 'startupjs'
4
+ import { themed } from '@startupjs-ui/core'
5
+ import AbstractPopover, { type AbstractPopoverProps } from '@startupjs-ui/abstract-popover'
6
+ import Div from '@startupjs-ui/div'
7
+ import './index.cssx.styl'
8
+
9
+ export const _PropsJsonSchema = {/* PopoverProps */}
10
+
11
+ export interface PopoverProps extends Omit<AbstractPopoverProps, 'anchorRef' | 'children' | 'style' | 'visible'> {
12
+ /** Ref to control popover programmatically */
13
+ ref?: RefObject<PopoverRef>
14
+ /** Custom styles for the anchor wrapper */
15
+ style?: StyleProp<ViewStyle>
16
+ /** Custom styles for the popover container */
17
+ attachmentStyle?: StyleProp<ViewStyle>
18
+ /** Custom styles for the dismiss overlay */
19
+ overlayStyle?: StyleProp<ViewStyle>
20
+ /** Controlled visibility flag */
21
+ visible?: boolean
22
+ /** Two-way binding value controlling visibility */
23
+ $visible?: any
24
+ /** Called when visibility should change */
25
+ onChange?: (visible: boolean) => void
26
+ /** Anchor content */
27
+ children?: ReactNode
28
+ /** Render function for popover content */
29
+ renderContent?: () => ReactNode
30
+ }
31
+
32
+ export interface PopoverRef {
33
+ /** Open the popover */
34
+ open: () => void
35
+ /** Close the popover */
36
+ close: () => void
37
+ }
38
+
39
+ function Popover ({
40
+ style,
41
+ attachmentStyle,
42
+ visible,
43
+ $visible,
44
+ children,
45
+ renderContent,
46
+ onChange,
47
+ renderWrapper,
48
+ overlayStyle,
49
+ ref,
50
+ ...props
51
+ }: PopoverProps): ReactNode {
52
+ const anchorRef = useRef<any>(null)
53
+
54
+ const isUncontrolled = useMemo(() => {
55
+ const isUsedViaTwoWayDataBinding = typeof $visible !== 'undefined'
56
+ const isUsedViaState = typeof onChange === 'function'
57
+ return !(isUsedViaTwoWayDataBinding || isUsedViaState)
58
+ // eslint-disable-next-line react-hooks/exhaustive-deps
59
+ }, [])
60
+
61
+ const $internalVisible = $(false)
62
+ const $effectiveVisible = isUncontrolled ? $internalVisible : $visible
63
+
64
+ ;({ visible, onChange } = useBind({ visible, $visible: $effectiveVisible, onChange }) as any)
65
+
66
+ const handleChange = useCallback((nextVisible: boolean) => {
67
+ if (typeof onChange === 'function') {
68
+ onChange(nextVisible)
69
+ return
70
+ }
71
+ if ($effectiveVisible) {
72
+ $effectiveVisible.set(nextVisible)
73
+ return
74
+ }
75
+ $internalVisible.set(nextVisible)
76
+ // eslint-disable-next-line react-hooks/exhaustive-deps
77
+ }, [])
78
+
79
+ useImperativeHandle(ref, () => ({
80
+ open: () => { handleChange(true) },
81
+ close: () => { handleChange(false) }
82
+ }), [handleChange])
83
+
84
+ const setVisibleTrue = useCallback(() => { handleChange(true) }, [handleChange])
85
+ const setVisibleFalse = useCallback(() => { handleChange(false) }, [handleChange])
86
+
87
+ const renderOverlayWrapper = (node: ReactNode): ReactNode => {
88
+ const wrappedNode = renderWrapper ? renderWrapper(node) : node
89
+ return pug`
90
+ View.root
91
+ TouchableWithoutFeedback(onPress=setVisibleFalse)
92
+ View.overlay(style=overlayStyle)
93
+ = wrappedNode
94
+ `
95
+ }
96
+
97
+ return pug`
98
+ Div(
99
+ style=style
100
+ ref=anchorRef
101
+ onPress=isUncontrolled ? null : setVisibleTrue
102
+ )= children
103
+ AbstractPopover.attachment(
104
+ ...props
105
+ visible=visible
106
+ style=[attachmentStyle]
107
+ anchorRef=anchorRef
108
+ renderWrapper=renderOverlayWrapper
109
+ )= renderContent && renderContent()
110
+ `
111
+ }
112
+
113
+ export default observer(themed('Popover', Popover))
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@startupjs-ui/popover",
3
+ "version": "0.1.3",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "main": "index.tsx",
8
+ "types": "index.d.ts",
9
+ "type": "module",
10
+ "dependencies": {
11
+ "@startupjs-ui/abstract-popover": "^0.1.3",
12
+ "@startupjs-ui/core": "^0.1.3",
13
+ "@startupjs-ui/div": "^0.1.3"
14
+ },
15
+ "peerDependencies": {
16
+ "react": "*",
17
+ "react-native": "*",
18
+ "startupjs": "*"
19
+ },
20
+ "gitHead": "fd964ebc3892d3dd0a6c85438c0af619cc50c3f0"
21
+ }