@purestack/ts-components 1.1.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 +10 -0
- package/dist/ts-components.d.mts +1662 -0
- package/dist/ts-components.d.mts.map +1 -0
- package/dist/ts-components.mjs +9200 -0
- package/dist/ts-components.mjs.map +1 -0
- package/package.json +130 -0
- package/src/defineComponents.ts +87 -0
- package/src/index.ts +270 -0
- package/src/registerStyles.ts +63 -0
- package/src/standard/alertBox/alertBox.ts +64 -0
- package/src/standard/autoId.ts +25 -0
- package/src/standard/badge/badge.ts +41 -0
- package/src/standard/badge/badgeStyle.ts +21 -0
- package/src/standard/barChart/barChart.ts +338 -0
- package/src/standard/barChart/barChartStyle.ts +81 -0
- package/src/standard/btn/btn.ts +191 -0
- package/src/standard/btn/btnStyle.ts +59 -0
- package/src/standard/btnGroup/btnGroup.ts +208 -0
- package/src/standard/btnGroup/btnGroupStyle.ts +85 -0
- package/src/standard/chart/cartesianChart.ts +99 -0
- package/src/standard/chart/chartDefaults.ts +25 -0
- package/src/standard/chart/chartUtils.ts +84 -0
- package/src/standard/classicLogo/classicLogo.ts +429 -0
- package/src/standard/classicLogo/classicLogoStyle.ts +292 -0
- package/src/standard/componentVariant.ts +153 -0
- package/src/standard/composer/composer.ts +1035 -0
- package/src/standard/composer/composerCanvasInitialStyle.ts +225 -0
- package/src/standard/composer/composerCanvasRevertStyle.ts +14 -0
- package/src/standard/composer/composerCanvasSharedStyle.ts +60 -0
- package/src/standard/composer/composerCanvasStyleTypes.ts +8 -0
- package/src/standard/composer/composerCanvasThemeStyle.ts +53 -0
- package/src/standard/composer/composerStyle.ts +156 -0
- package/src/standard/composer/emailHtmlPolicy.ts +474 -0
- package/src/standard/consent/consent.ts +173 -0
- package/src/standard/consent/consentStyle.ts +44 -0
- package/src/standard/contactForm/contactForm.ts +135 -0
- package/src/standard/contactForm/contactFormStyle.ts +116 -0
- package/src/standard/doughnutChart/doughnutChart.ts +527 -0
- package/src/standard/doughnutChart/doughnutChartStyle.ts +64 -0
- package/src/standard/dropFiles/dropFiles.ts +480 -0
- package/src/standard/dropFiles/dropFilesStyle.ts +171 -0
- package/src/standard/expandablePanel/expandablePanel.ts +106 -0
- package/src/standard/expandablePanel/expandablePanelStyle.ts +56 -0
- package/src/standard/flex/flex.ts +269 -0
- package/src/standard/flex/flexStyle.ts +556 -0
- package/src/standard/footer/footer.ts +93 -0
- package/src/standard/footer/footerStyle.ts +39 -0
- package/src/standard/form/autoCompleteInput.ts +567 -0
- package/src/standard/form/form.ts +205 -0
- package/src/standard/form/formCheck.ts +96 -0
- package/src/standard/form/formInputField.ts +184 -0
- package/src/standard/form/formSelectField.ts +152 -0
- package/src/standard/form/formStyle.ts +585 -0
- package/src/standard/form/multiAutoCompleteInput.ts +880 -0
- package/src/standard/grid/grid.ts +177 -0
- package/src/standard/grid/gridStyle.ts +56 -0
- package/src/standard/icon/icon.ts +96 -0
- package/src/standard/icon/iconStyle.ts +50 -0
- package/src/standard/landing/codeShowcase.ts +54 -0
- package/src/standard/landing/comparisonColumn.ts +30 -0
- package/src/standard/landing/comparisonFeature.ts +22 -0
- package/src/standard/landing/comparisonTable.ts +38 -0
- package/src/standard/landing/ctaSection.ts +59 -0
- package/src/standard/landing/featureCard.ts +41 -0
- package/src/standard/landing/landing.ts +52 -0
- package/src/standard/landing/landingBand.ts +217 -0
- package/src/standard/landing/landingSection.ts +43 -0
- package/src/standard/landing/landingTypes.ts +141 -0
- package/src/standard/landing/metricItem.ts +25 -0
- package/src/standard/landing/metricStrip.ts +20 -0
- package/src/standard/lineChart/lineChart.ts +462 -0
- package/src/standard/lineChart/lineChartStyle.ts +91 -0
- package/src/standard/logo/logo.ts +192 -0
- package/src/standard/logo/logoStyle.ts +164 -0
- package/src/standard/modal/modal.ts +171 -0
- package/src/standard/modal/modalStore.ts +154 -0
- package/src/standard/modal/modalStyle.ts +190 -0
- package/src/standard/navMenu/navMenu.ts +278 -0
- package/src/standard/navMenu/navMenuStyle.ts +323 -0
- package/src/standard/pageLinks/pageLinks.ts +90 -0
- package/src/standard/pageScript/pageScript.ts +155 -0
- package/src/standard/pageToc/pageToc.ts +154 -0
- package/src/standard/pageToc/pageTocStyle.ts +372 -0
- package/src/standard/panel/panel.ts +55 -0
- package/src/standard/panel/panelStyle.ts +15 -0
- package/src/standard/pricing/pricing.ts +146 -0
- package/src/standard/searchBox/searchBox.ts +54 -0
- package/src/standard/searchBox/searchBoxStyle.ts +180 -0
- package/src/standard/sectionHeader/sectionHeader.ts +99 -0
- package/src/standard/signIn/signIn.ts +167 -0
- package/src/standard/signIn/signInStyle.ts +70 -0
- package/src/standard/tabs/tabs.ts +193 -0
- package/src/standard/tabs/tabsStyle.ts +231 -0
- package/src/standard/themeToggle/themeToggle.ts +33 -0
- package/src/standard/themeToggle/themeToggleStyle.ts +88 -0
- package/src/standard/toast/toastHost.ts +42 -0
- package/src/standard/toast/toastStore.ts +50 -0
- package/src/standard/topBar/topBar.ts +101 -0
- package/src/standard/topBar/topBarStyle.ts +169 -0
- package/src/standard/virtualList/variableVirtualTable.ts +371 -0
- package/src/standard/virtualList/virtualList.ts +423 -0
- package/src/standard/virtualList/virtualListStyle.ts +34 -0
- package/src/standard/virtualList/virtualTable.ts +179 -0
- package/src/standard/virtualList/virtualTableStyle.ts +24 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { SemanticTone } from '@purestack/ts-style'
|
|
2
|
+
import { defineComponent, html, type RefOrValue } from 'regor'
|
|
3
|
+
import type {
|
|
4
|
+
ComponentVariant,
|
|
5
|
+
ComponentVariantMode,
|
|
6
|
+
} from '../componentVariant'
|
|
7
|
+
|
|
8
|
+
export interface PricingTable {
|
|
9
|
+
eyebrow?: RefOrValue<string>
|
|
10
|
+
title?: RefOrValue<string>
|
|
11
|
+
subtitle?: RefOrValue<string>
|
|
12
|
+
footnote?: RefOrValue<string>
|
|
13
|
+
tone?: RefOrValue<SemanticTone>
|
|
14
|
+
variant?: RefOrValue<ComponentVariant>
|
|
15
|
+
variantMode?: RefOrValue<ComponentVariantMode>
|
|
16
|
+
columns?: RefOrValue<number | string>
|
|
17
|
+
columnsLg?: RefOrValue<number | string>
|
|
18
|
+
columnsXl?: RefOrValue<number | string>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface PricingPlan {
|
|
22
|
+
title?: RefOrValue<string>
|
|
23
|
+
summary?: RefOrValue<string>
|
|
24
|
+
price?: RefOrValue<string>
|
|
25
|
+
period?: RefOrValue<string>
|
|
26
|
+
badge?: RefOrValue<string>
|
|
27
|
+
note?: RefOrValue<string>
|
|
28
|
+
variant?: RefOrValue<ComponentVariant>
|
|
29
|
+
variantMode?: RefOrValue<ComponentVariantMode>
|
|
30
|
+
icon?: RefOrValue<string>
|
|
31
|
+
ctaLabel?: RefOrValue<string>
|
|
32
|
+
ctaLink?: RefOrValue<string>
|
|
33
|
+
tone?: RefOrValue<SemanticTone>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface PricingFeature {
|
|
37
|
+
icon?: RefOrValue<string>
|
|
38
|
+
tone?: RefOrValue<SemanticTone>
|
|
39
|
+
variant?: RefOrValue<ComponentVariant>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const pricingTableTemplate = html`<Panel :tone="tone" :variant="variant || 'none'" :variantMode="variantMode">
|
|
43
|
+
<Flex direction="column" align="start">
|
|
44
|
+
<SectionHeader
|
|
45
|
+
r-if="eyebrow || title || subtitle || footnote"
|
|
46
|
+
:eyebrow="eyebrow"
|
|
47
|
+
:title="title"
|
|
48
|
+
:subtitle="subtitle"
|
|
49
|
+
:footnote="footnote"
|
|
50
|
+
titleTag="h2"/>
|
|
51
|
+
<Grid
|
|
52
|
+
:columns="columns || 1"
|
|
53
|
+
:columnsLg="columnsLg || 2"
|
|
54
|
+
:columnsXl="columnsXl || 4"
|
|
55
|
+
alignItems="stretch"
|
|
56
|
+
justifyItems="center"
|
|
57
|
+
>
|
|
58
|
+
<slot></slot>
|
|
59
|
+
</Grid>
|
|
60
|
+
</Flex>
|
|
61
|
+
</Panel>`
|
|
62
|
+
|
|
63
|
+
const pricingPlanTemplate = html`<Panel :tone="tone" :variant="variant || 'surface'" :variantMode="variantMode">
|
|
64
|
+
<Flex direction="column" align="start">
|
|
65
|
+
<Flex justify="between" align="center" r-if="icon || badge">
|
|
66
|
+
<IconFrame
|
|
67
|
+
r-if="icon"
|
|
68
|
+
:name="icon"
|
|
69
|
+
:tone="tone"
|
|
70
|
+
variant="surface"
|
|
71
|
+
size="lg"/>
|
|
72
|
+
<Badge r-if="badge" :tone="tone">{{ badge }}</Badge>
|
|
73
|
+
</Flex>
|
|
74
|
+
<SectionHeader :title="title" :subtitle="summary" titleTag="h3"/>
|
|
75
|
+
<Flex align="baseline" r-if="price">
|
|
76
|
+
<strong class="fs-h2">{{ price }}</strong>
|
|
77
|
+
<span r-if="period">{{ period }}</span>
|
|
78
|
+
</Flex>
|
|
79
|
+
<BtnLink :href="ctaLink" :tone="tone" r-if="ctaLabel && ctaLink">
|
|
80
|
+
{{ ctaLabel }}
|
|
81
|
+
</BtnLink>
|
|
82
|
+
<Flex container="ul" direction="column" align="start" class="m-0 p-0">
|
|
83
|
+
<slot></slot>
|
|
84
|
+
</Flex>
|
|
85
|
+
<small r-if="note">{{ note }}</small>
|
|
86
|
+
</Flex>
|
|
87
|
+
</Panel>`
|
|
88
|
+
|
|
89
|
+
const pricingFeatureTemplate = html`<Flex container="li" align="start">
|
|
90
|
+
<IconFrame
|
|
91
|
+
:name="icon || 'iconoir:check'"
|
|
92
|
+
:tone="tone"
|
|
93
|
+
:variant="variant || 'surface'"
|
|
94
|
+
size="sm"/>
|
|
95
|
+
<slot></slot>
|
|
96
|
+
</Flex>`
|
|
97
|
+
|
|
98
|
+
function definePricingTableComponent() {
|
|
99
|
+
return defineComponent<PricingTable>(pricingTableTemplate, {
|
|
100
|
+
props: [
|
|
101
|
+
'eyebrow',
|
|
102
|
+
'title',
|
|
103
|
+
'subtitle',
|
|
104
|
+
'footnote',
|
|
105
|
+
'tone',
|
|
106
|
+
'variant',
|
|
107
|
+
'variantMode',
|
|
108
|
+
'columns',
|
|
109
|
+
'columnsLg',
|
|
110
|
+
'columnsXl',
|
|
111
|
+
],
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function definePricingPlanComponent() {
|
|
116
|
+
return defineComponent<PricingPlan>(pricingPlanTemplate, {
|
|
117
|
+
props: [
|
|
118
|
+
'title',
|
|
119
|
+
'summary',
|
|
120
|
+
'price',
|
|
121
|
+
'period',
|
|
122
|
+
'badge',
|
|
123
|
+
'note',
|
|
124
|
+
'variant',
|
|
125
|
+
'variantMode',
|
|
126
|
+
'icon',
|
|
127
|
+
'ctaLabel',
|
|
128
|
+
'ctaLink',
|
|
129
|
+
'tone',
|
|
130
|
+
],
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function definePricingFeatureComponent() {
|
|
135
|
+
return defineComponent<PricingFeature>(pricingFeatureTemplate, {
|
|
136
|
+
props: ['icon', 'tone', 'variant'],
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function definePricingComponents() {
|
|
141
|
+
return {
|
|
142
|
+
pricingTable: definePricingTableComponent(),
|
|
143
|
+
pricingPlan: definePricingPlanComponent(),
|
|
144
|
+
pricingFeature: definePricingFeatureComponent(),
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { TsSsgContext } from '@purestack/ts-common'
|
|
2
|
+
|
|
3
|
+
import { resolveTsSsgContext } from '@purestack/ts-common'
|
|
4
|
+
import type { SemanticTone } from '@purestack/ts-style'
|
|
5
|
+
import { defineComponent, html, type RefOrValue } from 'regor'
|
|
6
|
+
import type { ComponentVariant } from '../componentVariant'
|
|
7
|
+
|
|
8
|
+
export interface SearchBox {
|
|
9
|
+
placeholder?: RefOrValue<string>
|
|
10
|
+
tone?: RefOrValue<SemanticTone>
|
|
11
|
+
variant?: RefOrValue<ComponentVariant>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const searchBoxTemplate = html`<div class="site-search" data-pagefind-search>
|
|
15
|
+
<FormInputField
|
|
16
|
+
icon="tabler:search"
|
|
17
|
+
:tone="tone"
|
|
18
|
+
:variant="variant"
|
|
19
|
+
type="search"
|
|
20
|
+
name="q"
|
|
21
|
+
:placeholder="placeholder"
|
|
22
|
+
autocomplete="off"
|
|
23
|
+
spellcheck="false"
|
|
24
|
+
data-pagefind-input
|
|
25
|
+
aria-label="Search site content"/>
|
|
26
|
+
<div
|
|
27
|
+
class="site-search__results doc-content"
|
|
28
|
+
data-pagefind-results
|
|
29
|
+
hidden
|
|
30
|
+
></div>
|
|
31
|
+
</div>`
|
|
32
|
+
|
|
33
|
+
function defineSearchBoxComponent() {
|
|
34
|
+
return defineComponent<SearchBox>(searchBoxTemplate, {
|
|
35
|
+
props: ['tone', 'variant', 'placeholder'],
|
|
36
|
+
context: (head) => ({
|
|
37
|
+
tone: head.props.tone,
|
|
38
|
+
variant: head.props.variant,
|
|
39
|
+
placeholder: resolveSearchPlaceholder(resolveTsSsgContext(head)),
|
|
40
|
+
}),
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function defineSearchComponents() {
|
|
45
|
+
return { searchBox: defineSearchBoxComponent() }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function resolveSearchPlaceholder(context: TsSsgContext): string {
|
|
49
|
+
const title = context?.site?.siteTitle
|
|
50
|
+
if (typeof title !== 'string') return 'Search'
|
|
51
|
+
const trimmed = title.trim()
|
|
52
|
+
if (trimmed.length === 0) return 'Search'
|
|
53
|
+
return `Search ${trimmed}`
|
|
54
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type { ThemePalette } from '@purestack/ts-style'
|
|
2
|
+
import {
|
|
3
|
+
BREAKPOINTS,
|
|
4
|
+
getBreakpoint,
|
|
5
|
+
mediaAbove,
|
|
6
|
+
styleBuilder,
|
|
7
|
+
type ThemeMode,
|
|
8
|
+
themes,
|
|
9
|
+
} from '@purestack/ts-style'
|
|
10
|
+
|
|
11
|
+
export function registerSearchBoxStyles() {
|
|
12
|
+
themes.forEach((theme, palette) => {
|
|
13
|
+
registerSearchBoxShellStyles(theme)
|
|
14
|
+
registerSearchBoxResultStyles(theme, palette)
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function registerSearchBoxShellStyles(theme: ThemeMode) {
|
|
19
|
+
registerSearchBoxShellContainerStyles(theme)
|
|
20
|
+
registerSearchBoxShellAccessibilityStyles(theme)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function registerSearchBoxShellContainerStyles(theme: ThemeMode) {
|
|
24
|
+
styleBuilder
|
|
25
|
+
.select('.site-search', theme)
|
|
26
|
+
.position('relative')
|
|
27
|
+
.maxWidth('100%')
|
|
28
|
+
|
|
29
|
+
styleBuilder.select('.site-search__field', theme).display('block')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function registerSearchBoxShellAccessibilityStyles(theme: ThemeMode) {
|
|
33
|
+
styleBuilder
|
|
34
|
+
.select('.site-search__sr-only', theme)
|
|
35
|
+
.position('absolute')
|
|
36
|
+
.width('1px')
|
|
37
|
+
.height('1px')
|
|
38
|
+
.padding('0')
|
|
39
|
+
.margin('-1px')
|
|
40
|
+
.overflow('hidden')
|
|
41
|
+
.clip('rect(0, 0, 0, 0)')
|
|
42
|
+
.whiteSpace('nowrap')
|
|
43
|
+
.border('0')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function registerSearchBoxResultStyles(
|
|
47
|
+
theme: ThemeMode,
|
|
48
|
+
palette: ThemePalette,
|
|
49
|
+
) {
|
|
50
|
+
registerSearchBoxResultContainerStyles(theme, palette)
|
|
51
|
+
registerSearchBoxResultTopBarOverlayStyles(theme)
|
|
52
|
+
registerSearchBoxResultListStyles(theme, palette)
|
|
53
|
+
registerSearchBoxResultContentStyles(theme, palette)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function registerSearchBoxResultContainerStyles(
|
|
57
|
+
theme: ThemeMode,
|
|
58
|
+
palette: ThemePalette,
|
|
59
|
+
) {
|
|
60
|
+
styleBuilder
|
|
61
|
+
.select('.site-search__results', theme)
|
|
62
|
+
.position('absolute')
|
|
63
|
+
.top('calc(100% + 0.5rem)')
|
|
64
|
+
.right('0')
|
|
65
|
+
.width('min(35rem, calc(100vw - 2rem))')
|
|
66
|
+
.maxHeight('26.25rem')
|
|
67
|
+
.overflow('auto')
|
|
68
|
+
.padding('0.5rem')
|
|
69
|
+
.borderRadius(palette.radii.lg)
|
|
70
|
+
.border(`1px solid ${palette.current.border.default}`)
|
|
71
|
+
.background(palette.current.surface.rest.background)
|
|
72
|
+
.boxShadow(palette.effect.strongShadow)
|
|
73
|
+
.zIndex('60')
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function registerSearchBoxResultTopBarOverlayStyles(theme: ThemeMode) {
|
|
77
|
+
styleBuilder
|
|
78
|
+
.select('.topbar .site-search__results', theme)
|
|
79
|
+
.media(mediaAbove(BREAKPOINTS.sm))
|
|
80
|
+
.position('fixed')
|
|
81
|
+
.top('4.75rem')
|
|
82
|
+
.left('50%')
|
|
83
|
+
.right('auto')
|
|
84
|
+
.transform('translateX(-50%)')
|
|
85
|
+
.width(`min(${getBreakpoint(BREAKPOINTS.sm)}, calc(100vw - 2rem))`)
|
|
86
|
+
.zIndex('120')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function registerSearchBoxResultListStyles(
|
|
90
|
+
theme: ThemeMode,
|
|
91
|
+
palette: ThemePalette,
|
|
92
|
+
) {
|
|
93
|
+
styleBuilder
|
|
94
|
+
.select('.site-search__results ul.site-search__list', theme)
|
|
95
|
+
.listStyle('none')
|
|
96
|
+
.margin('0')
|
|
97
|
+
.padding('0')
|
|
98
|
+
.display('grid')
|
|
99
|
+
.gap('0.5em')
|
|
100
|
+
|
|
101
|
+
styleBuilder
|
|
102
|
+
.select('.site-search__results .site-search__item', theme)
|
|
103
|
+
.margin('0')
|
|
104
|
+
.padding('0')
|
|
105
|
+
|
|
106
|
+
styleBuilder
|
|
107
|
+
.select('.site-search__results .site-search__link', theme)
|
|
108
|
+
.display('grid')
|
|
109
|
+
.gap('0.375rem')
|
|
110
|
+
.padding('0.75rem 0.875rem')
|
|
111
|
+
.borderRadius(palette.radii.md)
|
|
112
|
+
.border(`1px solid ${palette.current.border.subtle}`)
|
|
113
|
+
.background(palette.current.surface.rest.background)
|
|
114
|
+
.textDecoration('none')
|
|
115
|
+
.color(palette.current.text.default)
|
|
116
|
+
.transition(
|
|
117
|
+
'border-color 160ms ease, background-color 160ms ease, transform 160ms ease',
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
styleBuilder
|
|
121
|
+
.select('.site-search__results .site-search__link:hover', theme)
|
|
122
|
+
.background(palette.current.surfaceAlt.rest.background)
|
|
123
|
+
.borderColor(palette.current.border.default)
|
|
124
|
+
|
|
125
|
+
styleBuilder
|
|
126
|
+
.select('.site-search__results .site-search__link:focus-visible', theme)
|
|
127
|
+
.outline(`2px solid ${palette.current.border.focus}`)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function registerSearchBoxResultContentStyles(
|
|
131
|
+
theme: ThemeMode,
|
|
132
|
+
palette: ThemePalette,
|
|
133
|
+
) {
|
|
134
|
+
styleBuilder
|
|
135
|
+
.select('.site-search__results .site-search__title', theme)
|
|
136
|
+
.display('block')
|
|
137
|
+
.apply(palette.applyFont(palette.font.size.body, palette.font.weight.w700))
|
|
138
|
+
.color(palette.current.text.default)
|
|
139
|
+
.wordBreak('break-word')
|
|
140
|
+
|
|
141
|
+
styleBuilder
|
|
142
|
+
.select('.site-search__results .site-search__excerpt', theme)
|
|
143
|
+
.display('block')
|
|
144
|
+
.margin('0')
|
|
145
|
+
.apply(palette.applyFont(palette.font.size.sm))
|
|
146
|
+
.color(palette.current.text.subtle)
|
|
147
|
+
.wordBreak('break-word')
|
|
148
|
+
.display('-webkit-box')
|
|
149
|
+
.lineClamp('3')
|
|
150
|
+
.webkitBoxOrient('vertical')
|
|
151
|
+
.overflow('hidden')
|
|
152
|
+
|
|
153
|
+
styleBuilder
|
|
154
|
+
.select('.site-search__results mark.site-search__highlight', theme)
|
|
155
|
+
.padding('0 0.1875rem')
|
|
156
|
+
.borderRadius('0.3125rem')
|
|
157
|
+
.background(palette.current.button.hover.background)
|
|
158
|
+
.color(palette.current.button.hover.text)
|
|
159
|
+
|
|
160
|
+
styleBuilder
|
|
161
|
+
.select('.site-search__results .site-search__message', theme)
|
|
162
|
+
.margin('0')
|
|
163
|
+
.padding('0.625rem 0.75rem')
|
|
164
|
+
.borderRadius(palette.radii.md)
|
|
165
|
+
.border(`1px dashed ${palette.current.border.default}`)
|
|
166
|
+
.background(palette.current.surface.rest.background)
|
|
167
|
+
.color(palette.current.text.subtle)
|
|
168
|
+
|
|
169
|
+
styleBuilder
|
|
170
|
+
.select('.site-search__results .site-search__message--error', theme)
|
|
171
|
+
.border(`1px solid ${palette.semanticTone.danger.surface.rest.border}`)
|
|
172
|
+
.background(palette.semanticTone.danger.surface.rest.background)
|
|
173
|
+
.color(palette.semanticTone.danger.surface.rest.text)
|
|
174
|
+
|
|
175
|
+
styleBuilder
|
|
176
|
+
.select('.site-search__results .site-search__message--empty', theme)
|
|
177
|
+
.border(`1px solid ${palette.semanticTone.warning.surface.rest.border}`)
|
|
178
|
+
.background(palette.semanticTone.warning.surface.rest.background)
|
|
179
|
+
.color(palette.semanticTone.warning.surface.rest.text)
|
|
180
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ComputedRef,
|
|
3
|
+
computed,
|
|
4
|
+
defineComponent,
|
|
5
|
+
html,
|
|
6
|
+
type RefOrValue,
|
|
7
|
+
unref,
|
|
8
|
+
} from 'regor'
|
|
9
|
+
|
|
10
|
+
export interface SectionHeader {
|
|
11
|
+
eyebrow?: RefOrValue<string>
|
|
12
|
+
title?: RefOrValue<string>
|
|
13
|
+
subtitle?: RefOrValue<string>
|
|
14
|
+
footnote?: RefOrValue<string>
|
|
15
|
+
titleTag?: RefOrValue<string>
|
|
16
|
+
titleId?: RefOrValue<string>
|
|
17
|
+
eyebrowClass?: RefOrValue<string>
|
|
18
|
+
titleClass?: RefOrValue<string>
|
|
19
|
+
subtitleClass?: RefOrValue<string>
|
|
20
|
+
footnoteClass?: RefOrValue<string>
|
|
21
|
+
resolvedTitleTag?: ComputedRef<string>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const sectionHeaderTemplate = html`<div class="section-header">
|
|
25
|
+
<div class="text-eyebrow" :class="eyebrowClass" r-if="eyebrow">
|
|
26
|
+
{{ eyebrow }}
|
|
27
|
+
</div>
|
|
28
|
+
<div
|
|
29
|
+
:is="resolvedTitleTag"
|
|
30
|
+
:id="titleId"
|
|
31
|
+
class="text-title"
|
|
32
|
+
:class="titleClass"
|
|
33
|
+
r-if="title"
|
|
34
|
+
>
|
|
35
|
+
{{ title }}
|
|
36
|
+
</div>
|
|
37
|
+
<p class="text-tagline" :class="subtitleClass" r-if="subtitle">
|
|
38
|
+
{{ subtitle }}
|
|
39
|
+
</p>
|
|
40
|
+
<p class="prose-meta" :class="footnoteClass" r-if="footnote">
|
|
41
|
+
{{ footnote }}
|
|
42
|
+
</p>
|
|
43
|
+
<slot></slot>
|
|
44
|
+
</div>`
|
|
45
|
+
|
|
46
|
+
function defineSectionHeaderComponent() {
|
|
47
|
+
return defineComponent<SectionHeader>(sectionHeaderTemplate, {
|
|
48
|
+
props: [
|
|
49
|
+
'eyebrow',
|
|
50
|
+
'title',
|
|
51
|
+
'subtitle',
|
|
52
|
+
'footnote',
|
|
53
|
+
'titleTag',
|
|
54
|
+
'titleId',
|
|
55
|
+
'eyebrowClass',
|
|
56
|
+
'titleClass',
|
|
57
|
+
'subtitleClass',
|
|
58
|
+
'footnoteClass',
|
|
59
|
+
],
|
|
60
|
+
context: (head) => resolveSectionHeader(head.props),
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function defineSectionHeaderComponents() {
|
|
65
|
+
return {
|
|
66
|
+
sectionHeader: defineSectionHeaderComponent(),
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function resolveSectionHeader(props: SectionHeader): SectionHeader {
|
|
71
|
+
return {
|
|
72
|
+
...props,
|
|
73
|
+
resolvedTitleTag: computed(() => resolveTitleTag(unref(props.titleTag))),
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function resolveTitleTag(value: unknown): string {
|
|
78
|
+
const normalized = resolveString(value).toLowerCase()
|
|
79
|
+
if (
|
|
80
|
+
normalized === 'h1' ||
|
|
81
|
+
normalized === 'h2' ||
|
|
82
|
+
normalized === 'h3' ||
|
|
83
|
+
normalized === 'h4' ||
|
|
84
|
+
normalized === 'h5' ||
|
|
85
|
+
normalized === 'h6' ||
|
|
86
|
+
normalized === 'p' ||
|
|
87
|
+
normalized === 'div' ||
|
|
88
|
+
normalized === 'span'
|
|
89
|
+
) {
|
|
90
|
+
return normalized
|
|
91
|
+
}
|
|
92
|
+
return 'h2'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function resolveString(value: unknown) {
|
|
96
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
97
|
+
? value.trim()
|
|
98
|
+
: ''
|
|
99
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { tryResolveTsSsgContext } from '@purestack/ts-common'
|
|
2
|
+
import type { SemanticTone } from '@purestack/ts-style'
|
|
3
|
+
import {
|
|
4
|
+
type ComputedRef,
|
|
5
|
+
computed,
|
|
6
|
+
defineComponent,
|
|
7
|
+
html,
|
|
8
|
+
type RefOrValue,
|
|
9
|
+
unref,
|
|
10
|
+
} from 'regor'
|
|
11
|
+
import type {
|
|
12
|
+
ComponentVariant,
|
|
13
|
+
ComponentVariantMode,
|
|
14
|
+
} from '../componentVariant'
|
|
15
|
+
|
|
16
|
+
export interface SignIn {
|
|
17
|
+
avatarSrc?: RefOrValue<string>
|
|
18
|
+
avatarAlt?: RefOrValue<string>
|
|
19
|
+
icon?: RefOrValue<string>
|
|
20
|
+
accountIcon?: RefOrValue<string>
|
|
21
|
+
label?: RefOrValue<string>
|
|
22
|
+
tone?: RefOrValue<SemanticTone>
|
|
23
|
+
variant?: RefOrValue<ComponentVariant>
|
|
24
|
+
variantMode?: RefOrValue<ComponentVariantMode>
|
|
25
|
+
authEnabled?: boolean
|
|
26
|
+
signUpEnabled?: boolean
|
|
27
|
+
resolvedIcon?: ComputedRef<string>
|
|
28
|
+
resolvedAccountIcon?: ComputedRef<string>
|
|
29
|
+
resolvedLabel?: ComputedRef<string>
|
|
30
|
+
resolvedAvatarAlt?: ComputedRef<string>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const DEFAULT_SIGN_IN_ICON = 'lucide:log-in'
|
|
34
|
+
const DEFAULT_ACCOUNT_ICON = 'tabler:user-filled'
|
|
35
|
+
const DEFAULT_SIGN_IN_LABEL = 'Account'
|
|
36
|
+
|
|
37
|
+
const signInTemplate = html`<details
|
|
38
|
+
r-if="authEnabled"
|
|
39
|
+
class="sign-in position-relative"
|
|
40
|
+
data-menu-runtime
|
|
41
|
+
data-menu-align="end"
|
|
42
|
+
>
|
|
43
|
+
<summary
|
|
44
|
+
class="sign-in__trigger topbar__icon rounded-pill cursor-pointer overflow-hidden"
|
|
45
|
+
aria-label="Account menu"
|
|
46
|
+
>
|
|
47
|
+
<span
|
|
48
|
+
class="sign-in__signed-out-view tone-fill-surface-hover tone-fill-surface-active tone-border-surface-hover tone-border-surface-active"
|
|
49
|
+
aria-hidden="true"
|
|
50
|
+
>
|
|
51
|
+
<Icon :name="resolvedIcon"/>
|
|
52
|
+
</span>
|
|
53
|
+
<span
|
|
54
|
+
class="sign-in__signed-in-view tone-fill-surface-hover tone-fill-surface-active tone-border-surface-hover tone-border-surface-active"
|
|
55
|
+
aria-hidden="true"
|
|
56
|
+
>
|
|
57
|
+
<slot name="avatar">
|
|
58
|
+
<img
|
|
59
|
+
r-if="avatarSrc"
|
|
60
|
+
class="sign-in__avatar w-full h-full rounded-pill"
|
|
61
|
+
:src="avatarSrc"
|
|
62
|
+
:alt="resolvedAvatarAlt"/>
|
|
63
|
+
<Icon r-else :name="resolvedAccountIcon"/>
|
|
64
|
+
</slot>
|
|
65
|
+
</span>
|
|
66
|
+
<span class="hidden">{{ resolvedLabel }}</span>
|
|
67
|
+
</summary>
|
|
68
|
+
<Panel
|
|
69
|
+
class="sign-in__panel p-1 mt-1"
|
|
70
|
+
:tone="tone"
|
|
71
|
+
:variant="variant || 'surfaceAlt'"
|
|
72
|
+
:variantMode="variantMode"
|
|
73
|
+
data-menu-panel
|
|
74
|
+
>
|
|
75
|
+
<slot>
|
|
76
|
+
<Flex
|
|
77
|
+
container="nav"
|
|
78
|
+
direction="column"
|
|
79
|
+
align="stretch"
|
|
80
|
+
class="gap-1"
|
|
81
|
+
aria-label="Account"
|
|
82
|
+
>
|
|
83
|
+
<BtnLink
|
|
84
|
+
class="sign-in__signed-out-action justify-start w-full text-start"
|
|
85
|
+
href="/signin/"
|
|
86
|
+
:tone="tone"
|
|
87
|
+
variant="subtleBtn"
|
|
88
|
+
icon="lucide:log-in"
|
|
89
|
+
>
|
|
90
|
+
Sign in
|
|
91
|
+
</BtnLink>
|
|
92
|
+
<BtnLink
|
|
93
|
+
r-if="signUpEnabled"
|
|
94
|
+
class="sign-in__signed-out-action justify-start w-full text-start"
|
|
95
|
+
href="/signup/"
|
|
96
|
+
:tone="tone"
|
|
97
|
+
variant="subtleBtn"
|
|
98
|
+
icon="lucide:user-plus"
|
|
99
|
+
>
|
|
100
|
+
Sign up
|
|
101
|
+
</BtnLink>
|
|
102
|
+
<BtnLink
|
|
103
|
+
class="sign-in__signed-in-action justify-start w-full text-start"
|
|
104
|
+
href="/account/"
|
|
105
|
+
:tone="tone"
|
|
106
|
+
variant="subtleBtn"
|
|
107
|
+
icon="lucide:user-round"
|
|
108
|
+
>
|
|
109
|
+
Account
|
|
110
|
+
</BtnLink>
|
|
111
|
+
<BtnLink
|
|
112
|
+
class="sign-in__signed-in-action justify-start w-full text-start"
|
|
113
|
+
href="/account/settings/"
|
|
114
|
+
:tone="tone"
|
|
115
|
+
variant="subtleBtn"
|
|
116
|
+
icon="lucide:settings"
|
|
117
|
+
>
|
|
118
|
+
Settings
|
|
119
|
+
</BtnLink>
|
|
120
|
+
<BtnLink
|
|
121
|
+
class="sign-in__signed-in-action justify-start w-full text-start"
|
|
122
|
+
href="/signout/"
|
|
123
|
+
:tone="tone"
|
|
124
|
+
variant="subtleBtn"
|
|
125
|
+
icon="lucide:log-out"
|
|
126
|
+
>
|
|
127
|
+
Sign out
|
|
128
|
+
</BtnLink>
|
|
129
|
+
</Flex>
|
|
130
|
+
</slot>
|
|
131
|
+
</Panel>
|
|
132
|
+
</details>`
|
|
133
|
+
|
|
134
|
+
function defineSignInComponent() {
|
|
135
|
+
return defineComponent<SignIn>(signInTemplate, {
|
|
136
|
+
props: [
|
|
137
|
+
'avatarSrc',
|
|
138
|
+
'avatarAlt',
|
|
139
|
+
'icon',
|
|
140
|
+
'accountIcon',
|
|
141
|
+
'label',
|
|
142
|
+
'tone',
|
|
143
|
+
'variant',
|
|
144
|
+
'variantMode',
|
|
145
|
+
],
|
|
146
|
+
context: (head) => resolveSignIn(head.props, head),
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function defineSignInComponents() {
|
|
151
|
+
return { signIn: defineSignInComponent() }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function resolveSignIn(props: SignIn, head: unknown): SignIn {
|
|
155
|
+
const auth = tryResolveTsSsgContext(head)?.site?.auth
|
|
156
|
+
return {
|
|
157
|
+
...props,
|
|
158
|
+
authEnabled: auth?.enabled === true,
|
|
159
|
+
signUpEnabled: auth?.signUp === true,
|
|
160
|
+
resolvedIcon: computed(() => unref(props.icon) || DEFAULT_SIGN_IN_ICON),
|
|
161
|
+
resolvedAccountIcon: computed(
|
|
162
|
+
() => unref(props.accountIcon) || DEFAULT_ACCOUNT_ICON,
|
|
163
|
+
),
|
|
164
|
+
resolvedLabel: computed(() => unref(props.label) || DEFAULT_SIGN_IN_LABEL),
|
|
165
|
+
resolvedAvatarAlt: computed(() => unref(props.avatarAlt) || ''),
|
|
166
|
+
}
|
|
167
|
+
}
|