@startupjs-ui/link 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 +20 -0
- package/README.mdx +148 -0
- package/index.cssx.styl +12 -0
- package/index.d.ts +36 -0
- package/index.tsx +142 -0
- package/package.json +22 -0
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/link
|
|
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
|
+
* **link:** refactor Link component ([2729a36](https://github.com/startupjs/startupjs-ui/commit/2729a36d48b7930a3182c0c69070541e1bd2cf8c))
|
package/README.mdx
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import Link, { _PropsJsonSchema as LinkPropsJsonSchema } from './index'
|
|
2
|
+
import Br from '@startupjs-ui/br'
|
|
3
|
+
import Button from '@startupjs-ui/button'
|
|
4
|
+
import Div from '@startupjs-ui/div'
|
|
5
|
+
import Rating from '@startupjs-ui/rating'
|
|
6
|
+
import { u } from 'startupjs'
|
|
7
|
+
import { Sandbox } from '@startupjs-ui/docs'
|
|
8
|
+
|
|
9
|
+
# Link
|
|
10
|
+
|
|
11
|
+
Link allows to navigate of the app and customize anchors.
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
import { Link } from 'startupjs-ui'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Simple example
|
|
18
|
+
|
|
19
|
+
```jsx example
|
|
20
|
+
return (
|
|
21
|
+
<Link to='/docs/Card'>
|
|
22
|
+
Card
|
|
23
|
+
</Link>
|
|
24
|
+
)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Different display
|
|
28
|
+
|
|
29
|
+
There are two options `inline` and `block` of the `display` property. It is detected automatically based on the type of `children`, if not specified. When type of `children` is string it `inline` and `block` otherwise. Depending on the `display` property, component has a different appearance.
|
|
30
|
+
|
|
31
|
+
```jsx example
|
|
32
|
+
return (
|
|
33
|
+
<Div>
|
|
34
|
+
<Link to='/docs/Card'>
|
|
35
|
+
Card
|
|
36
|
+
</Link>
|
|
37
|
+
<Br />
|
|
38
|
+
<Link to='/docs/Rating'>
|
|
39
|
+
<Rating value={4.5} readonly />
|
|
40
|
+
</Link>
|
|
41
|
+
</Div>
|
|
42
|
+
)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Colors
|
|
46
|
+
|
|
47
|
+
To change link color pass the property `color` (works only when `display` value is `inline`).
|
|
48
|
+
|
|
49
|
+
```jsx example
|
|
50
|
+
return (
|
|
51
|
+
<Link
|
|
52
|
+
to='/docs/Card'
|
|
53
|
+
color='primary'
|
|
54
|
+
>
|
|
55
|
+
Card
|
|
56
|
+
</Link>
|
|
57
|
+
)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Bold link
|
|
61
|
+
|
|
62
|
+
To make link text bold pass the property `bold` to component.
|
|
63
|
+
|
|
64
|
+
```jsx example
|
|
65
|
+
return (
|
|
66
|
+
<Link to='/docs/Card' bold>
|
|
67
|
+
Card
|
|
68
|
+
</Link>
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Italic link
|
|
73
|
+
|
|
74
|
+
To make link text italic pass the property `italic` to component.
|
|
75
|
+
|
|
76
|
+
```jsx example
|
|
77
|
+
return (
|
|
78
|
+
<Link to='/docs/Card' italic>
|
|
79
|
+
Card
|
|
80
|
+
</Link>
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Hover style
|
|
85
|
+
|
|
86
|
+
You can change hover style like in [Div component](/docs/Div) by passing `variant='highlight'` (works only when `display` value is `block`).
|
|
87
|
+
|
|
88
|
+
```jsx example
|
|
89
|
+
const style = {
|
|
90
|
+
height: u(10),
|
|
91
|
+
backgroundColor: 'white',
|
|
92
|
+
alignItems: 'center',
|
|
93
|
+
justifyContent: 'center'
|
|
94
|
+
}
|
|
95
|
+
return (
|
|
96
|
+
<Link
|
|
97
|
+
style={style}
|
|
98
|
+
to='/docs/Rating'
|
|
99
|
+
variant='highlight'
|
|
100
|
+
>
|
|
101
|
+
<Rating value={4.5} readonly />
|
|
102
|
+
</Link>
|
|
103
|
+
)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Button as link
|
|
107
|
+
|
|
108
|
+
Sometimes you want to make button as link. The example below illustrates how to do this correctly.
|
|
109
|
+
|
|
110
|
+
```jsx example
|
|
111
|
+
return (
|
|
112
|
+
<Link
|
|
113
|
+
to='/docs/Card'
|
|
114
|
+
>
|
|
115
|
+
<Button color='primary' variant='flat'>Card</Button>
|
|
116
|
+
</Link>
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Actions
|
|
121
|
+
|
|
122
|
+
By passing `onPress` handler to component you can run some logic before redirecting.
|
|
123
|
+
|
|
124
|
+
```jsx example
|
|
125
|
+
function onPress (event) {
|
|
126
|
+
console.log('Go to alert docs')
|
|
127
|
+
}
|
|
128
|
+
return (
|
|
129
|
+
<Link
|
|
130
|
+
color='primary'
|
|
131
|
+
to='/docs/Alert'
|
|
132
|
+
onPress={onPress}
|
|
133
|
+
>
|
|
134
|
+
Alert docs
|
|
135
|
+
</Link>
|
|
136
|
+
)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Sandbox
|
|
140
|
+
|
|
141
|
+
<Sandbox
|
|
142
|
+
Component={Link}
|
|
143
|
+
propsJsonSchema={LinkPropsJsonSchema}
|
|
144
|
+
props={{
|
|
145
|
+
to: '#',
|
|
146
|
+
children: 'StartupJS'
|
|
147
|
+
}}
|
|
148
|
+
/>
|
package/index.cssx.styl
ADDED
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 } from 'react';
|
|
5
|
+
import { type StyleProp, type TextStyle, type ViewStyle } from 'react-native';
|
|
6
|
+
import { type DivProps } from '@startupjs-ui/div';
|
|
7
|
+
import './index.cssx.styl';
|
|
8
|
+
declare const _default: import("react").ComponentType<LinkProps>;
|
|
9
|
+
export default _default;
|
|
10
|
+
export declare const _PropsJsonSchema: {};
|
|
11
|
+
export interface LinkProps extends Omit<DivProps, 'style'> {
|
|
12
|
+
/** Custom styles applied to the root view */
|
|
13
|
+
style?: StyleProp<TextStyle | ViewStyle>;
|
|
14
|
+
/** Content rendered inside Link */
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
/** Link target path or URL */
|
|
17
|
+
to?: string;
|
|
18
|
+
/** Alias for `to` */
|
|
19
|
+
href?: string;
|
|
20
|
+
/** Use router push instead of navigate */
|
|
21
|
+
push?: boolean;
|
|
22
|
+
/** Replace current history entry instead of pushing */
|
|
23
|
+
replace?: boolean;
|
|
24
|
+
/** Display mode @default auto-detected */
|
|
25
|
+
display?: 'inline' | 'block';
|
|
26
|
+
/** Color variant for inline links @default 'default' */
|
|
27
|
+
color?: 'default' | 'primary';
|
|
28
|
+
/** Theme name used for styling */
|
|
29
|
+
theme?: string;
|
|
30
|
+
/** Render text in bold style when inline @default false */
|
|
31
|
+
bold?: boolean;
|
|
32
|
+
/** Render text in italic style when inline @default false */
|
|
33
|
+
italic?: boolean;
|
|
34
|
+
/** onPress handler */
|
|
35
|
+
onPress?: (event: any) => void;
|
|
36
|
+
}
|
package/index.tsx
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { Children, cloneElement, type ReactNode } from 'react'
|
|
2
|
+
import { Linking, Platform, type StyleProp, type TextStyle, type ViewStyle } from 'react-native'
|
|
3
|
+
import { pug, observer } from 'startupjs'
|
|
4
|
+
import useRouter from 'startupjs/useRouter'
|
|
5
|
+
import { themed } from '@startupjs-ui/core'
|
|
6
|
+
import Button from '@startupjs-ui/button'
|
|
7
|
+
import Div, { type DivProps } from '@startupjs-ui/div'
|
|
8
|
+
import Span from '@startupjs-ui/span'
|
|
9
|
+
import './index.cssx.styl'
|
|
10
|
+
|
|
11
|
+
const isWeb = Platform.OS === 'web'
|
|
12
|
+
const EXTERNAL_LINK_REGEXP = /^(https?:\/\/|\/\/)/i
|
|
13
|
+
|
|
14
|
+
export default observer(themed('Link', Link))
|
|
15
|
+
|
|
16
|
+
export const _PropsJsonSchema = {/* LinkProps */} // used in docs generation
|
|
17
|
+
export interface LinkProps extends Omit<DivProps, 'style'> {
|
|
18
|
+
/** Custom styles applied to the root view */
|
|
19
|
+
style?: StyleProp<TextStyle | ViewStyle>
|
|
20
|
+
/** Content rendered inside Link */
|
|
21
|
+
children?: ReactNode
|
|
22
|
+
/** Link target path or URL */
|
|
23
|
+
to?: string
|
|
24
|
+
/** Alias for `to` */
|
|
25
|
+
href?: string
|
|
26
|
+
/** Use router push instead of navigate */
|
|
27
|
+
push?: boolean
|
|
28
|
+
/** Replace current history entry instead of pushing */
|
|
29
|
+
replace?: boolean
|
|
30
|
+
/** Display mode @default auto-detected */
|
|
31
|
+
display?: 'inline' | 'block'
|
|
32
|
+
/** Color variant for inline links @default 'default' */
|
|
33
|
+
color?: 'default' | 'primary'
|
|
34
|
+
/** Theme name used for styling */
|
|
35
|
+
theme?: string
|
|
36
|
+
/** Render text in bold style when inline @default false */
|
|
37
|
+
bold?: boolean
|
|
38
|
+
/** Render text in italic style when inline @default false */
|
|
39
|
+
italic?: boolean
|
|
40
|
+
/** onPress handler */
|
|
41
|
+
onPress?: (event: any) => void
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function Link ({
|
|
45
|
+
style,
|
|
46
|
+
to,
|
|
47
|
+
href,
|
|
48
|
+
color = 'default',
|
|
49
|
+
theme,
|
|
50
|
+
display,
|
|
51
|
+
push,
|
|
52
|
+
replace = false,
|
|
53
|
+
children,
|
|
54
|
+
onPress,
|
|
55
|
+
...restProps
|
|
56
|
+
}: LinkProps): ReactNode {
|
|
57
|
+
let bold = restProps.bold
|
|
58
|
+
let italic = restProps.italic
|
|
59
|
+
if (bold == null) bold = false
|
|
60
|
+
if (italic == null) italic = false
|
|
61
|
+
restProps.bold = bold
|
|
62
|
+
restProps.italic = italic
|
|
63
|
+
|
|
64
|
+
let target = to ?? ''
|
|
65
|
+
if (href) target = href
|
|
66
|
+
|
|
67
|
+
let resolvedDisplay = display
|
|
68
|
+
if (!resolvedDisplay) resolvedDisplay = typeof children === 'string' ? 'inline' : 'block'
|
|
69
|
+
|
|
70
|
+
const isBlock = resolvedDisplay === 'block'
|
|
71
|
+
const Component = isBlock ? Div : Span
|
|
72
|
+
const extraProps: Record<string, any> = { accessibilityRole: 'link', onPress: handlePress }
|
|
73
|
+
const {
|
|
74
|
+
navigate: routerNavigate,
|
|
75
|
+
push: routerPush,
|
|
76
|
+
replace: routerReplace,
|
|
77
|
+
usePathname
|
|
78
|
+
} = useRouter()
|
|
79
|
+
|
|
80
|
+
const pathname = usePathname()
|
|
81
|
+
|
|
82
|
+
if (isWeb) {
|
|
83
|
+
let hrefValue = target ?? ''
|
|
84
|
+
if (!EXTERNAL_LINK_REGEXP.test(hrefValue) && !/^[/?#]/.test(hrefValue)) {
|
|
85
|
+
let p = pathname
|
|
86
|
+
p = p.replace(/#.*$/, '')
|
|
87
|
+
p = p.replace(/\?.*$/, '')
|
|
88
|
+
p = p.replace(/\/$/, '')
|
|
89
|
+
hrefValue = hrefValue.replace(/^\//, '')
|
|
90
|
+
hrefValue = hrefValue.replace(/\/$/, '')
|
|
91
|
+
hrefValue = p + '/' + hrefValue
|
|
92
|
+
}
|
|
93
|
+
extraProps.href = hrefValue
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function handlePress (event: any) {
|
|
97
|
+
if (onPress) onPress(event)
|
|
98
|
+
|
|
99
|
+
if (!event.defaultPrevented) {
|
|
100
|
+
if (isWeb) {
|
|
101
|
+
if (isModifiedEvent(event)) return
|
|
102
|
+
event.preventDefault()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (EXTERNAL_LINK_REGEXP.test(target ?? '')) {
|
|
106
|
+
isWeb
|
|
107
|
+
? window.open(target, '_blank')
|
|
108
|
+
: Linking.openURL(target ?? '')
|
|
109
|
+
} else {
|
|
110
|
+
let method
|
|
111
|
+
if (push) method = routerPush
|
|
112
|
+
else if (replace) method = routerReplace
|
|
113
|
+
else method = routerNavigate
|
|
114
|
+
method(target)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (isBlock) {
|
|
120
|
+
try {
|
|
121
|
+
Children.only(children as any)
|
|
122
|
+
if ((children as any)?.props?.originalType === Button || (children as any)?.type === Button) {
|
|
123
|
+
return cloneElement(children as any, { style, ...restProps, ...extraProps })
|
|
124
|
+
}
|
|
125
|
+
} catch (e) {
|
|
126
|
+
// ignore errors when children contains multiple elements
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return pug`
|
|
131
|
+
Component.root(
|
|
132
|
+
style=style
|
|
133
|
+
styleName=[theme, color, resolvedDisplay]
|
|
134
|
+
...restProps
|
|
135
|
+
...extraProps
|
|
136
|
+
)= children
|
|
137
|
+
`
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function isModifiedEvent (event: any) {
|
|
141
|
+
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey)
|
|
142
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@startupjs-ui/link",
|
|
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/button": "^0.1.3",
|
|
12
|
+
"@startupjs-ui/core": "^0.1.3",
|
|
13
|
+
"@startupjs-ui/div": "^0.1.3",
|
|
14
|
+
"@startupjs-ui/span": "^0.1.3"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"react": "*",
|
|
18
|
+
"react-native": "*",
|
|
19
|
+
"startupjs": "*"
|
|
20
|
+
},
|
|
21
|
+
"gitHead": "fd964ebc3892d3dd0a6c85438c0af619cc50c3f0"
|
|
22
|
+
}
|