mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 19:58:09 +00:00
Add wizard (#2571)
Signed-off-by: Sergei Ogorelkov <sergei.ogorelkov@xored.com>
This commit is contained in:
parent
6e0b1d1036
commit
67e86538bb
59
packages/ui/src/components/wizard/Wizard.svelte
Normal file
59
packages/ui/src/components/wizard/Wizard.svelte
Normal file
@ -0,0 +1,59 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
// Copyright © 2021 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getPlatformColor } from '../../colors'
|
||||
import { Component, WizardModel, WizardItemPosition } from '../..'
|
||||
import ScrollerBar from '../ScrollerBar.svelte'
|
||||
import WizardStep from './WizardStep.svelte'
|
||||
|
||||
export let items: readonly WizardModel[]
|
||||
export let selected = 0
|
||||
export let gap: 'none' | 'small' | 'big' = 'none'
|
||||
|
||||
const COLOR = 9
|
||||
|
||||
let divScroll: HTMLElement
|
||||
let selectedItem: WizardModel | undefined
|
||||
|
||||
function getPosition (n: number): WizardItemPosition {
|
||||
if (n === 0) return 'start'
|
||||
else if (n === items.length - 1) return 'end'
|
||||
else return 'middle'
|
||||
}
|
||||
|
||||
$: selectedItem = items[selected]
|
||||
</script>
|
||||
|
||||
<ScrollerBar {gap} bind:scroller={divScroll}>
|
||||
{#each items as item, i}
|
||||
<WizardStep
|
||||
label={item.label}
|
||||
position={getPosition(i)}
|
||||
positionState={selected === i ? 'current' : i < selected ? 'prev' : 'next'}
|
||||
prevColor={getPlatformColor(COLOR)}
|
||||
currentColor={getPlatformColor(COLOR)}
|
||||
nextColor="var(--theme-bg-focused-color)"
|
||||
/>
|
||||
{/each}
|
||||
</ScrollerBar>
|
||||
|
||||
{#if selectedItem}
|
||||
{#if typeof selectedItem.component === 'string'}
|
||||
<Component is={selectedItem.component} props={selectedItem.props} on:change />
|
||||
{:else}
|
||||
<svelte:component this={selectedItem.component} {...selectedItem.props} on:change />
|
||||
{/if}
|
||||
{/if}
|
142
packages/ui/src/components/wizard/WizardStep.svelte
Normal file
142
packages/ui/src/components/wizard/WizardStep.svelte
Normal file
@ -0,0 +1,142 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
// Copyright © 2021 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { IntlString, translate } from '@hcengineering/platform'
|
||||
import { afterUpdate } from 'svelte'
|
||||
import { WizardItemPosition, WizardItemPositionState } from '../..'
|
||||
|
||||
export let label: IntlString
|
||||
export let position: WizardItemPosition
|
||||
export let positionState: WizardItemPositionState
|
||||
export let currentColor = 'var(--theme-bg-focused-color)'
|
||||
export let prevColor = 'var(--theme-bg-focused-color)'
|
||||
export let nextColor = 'var(--theme-bg-accent-color)'
|
||||
|
||||
let lenght: number = 0
|
||||
let text: HTMLElement
|
||||
let divBar: HTMLElement
|
||||
let svgBack: SVGElement
|
||||
let style: string
|
||||
let translation: string | undefined
|
||||
|
||||
function getStyle (state: typeof positionState) {
|
||||
switch (state) {
|
||||
case 'current':
|
||||
return `fill: ${currentColor};`
|
||||
case 'prev':
|
||||
return `fill: ${prevColor};`
|
||||
case 'next':
|
||||
return `fill: ${nextColor};`
|
||||
}
|
||||
}
|
||||
|
||||
$: style = getStyle(positionState)
|
||||
$: label && translate(label, {}).then((t) => (translation = t))
|
||||
|
||||
afterUpdate(() => {
|
||||
if (text) lenght = text.clientWidth + 32 > 300 ? 300 : text.clientWidth + 32
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if translation}
|
||||
<div class="hidden-text text-md font-medium" bind:this={text}>{translation}</div>
|
||||
{#if lenght > 0}
|
||||
<div class="flex-row">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div bind:this={divBar} class="bar" on:click|stopPropagation>
|
||||
<svg
|
||||
bind:this={svgBack}
|
||||
class="bar__back"
|
||||
viewBox="0 0 {lenght} 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
{#if position === 'start'}
|
||||
<path
|
||||
class="bar__element"
|
||||
{style}
|
||||
d="M0,5.3C0,2.4,2.3,0,5.2,0h1.3h{lenght -
|
||||
13}h1.2c0.5,0,1,0.3,1.2,0.9l4,10.7c0.1,0.3,0.1,0.7,0,0.9l-4,10.7c-0.2,0.5-0.7,0.9-1.2,0.9 l-1.2,0h-{lenght -
|
||||
13}H5.2C2.3,24,0,21.6,0,18.7V5.3z"
|
||||
/>
|
||||
{:else if position === 'middle'}
|
||||
<path
|
||||
class="bar__element"
|
||||
{style}
|
||||
d="M4,11.5L0.1,0.9C-0.1,0.5,0.2,0,0.6,0h5.8h{lenght -
|
||||
13}h1.2c0.5,0,1,0.3,1.2,0.9l4,10.7c0.1,0.3,0.1,0.7,0,0.9l-4,10.7 c-0.2,0.5-0.7,0.9-1.2,0.9h-1.2h-{lenght -
|
||||
13}H0.6c-0.5,0-0.8-0.5-0.6-0.9L4,12.5C4.1,12.2,4.1,11.8,4,11.5z"
|
||||
/>
|
||||
{:else if position === 'end'}
|
||||
<path
|
||||
class="bar__element"
|
||||
{style}
|
||||
d="M4.1,11.5l-4-10.6C-0.1,0.5,0.2,0,0.7,0h{lenght - 7}C{lenght -
|
||||
3},0,{lenght},2.4,{lenght},5.3v13.3c0,2.9-2.4,5.3-5.3,5.3h-{lenght}H0.6c-0.5,0-0.8-0.5-0.6-0.9L4,12.5C4.1,12.2,4.1,11.8,4,11.5z"
|
||||
/>
|
||||
{:else}
|
||||
<path
|
||||
class="bar__element"
|
||||
{style}
|
||||
d="M0,5.3C0,2.4,2.3,0,5.2,0h1.3h{lenght}h1.3C49.7,0,52,2.4,52,5.3v13.3c0,2.9-2.3,5.3-5.2,5.3h-1.3h-{lenght}H5.2 C2.3,24,0,21.6,0,18.7V5.3z"
|
||||
/>
|
||||
{/if}
|
||||
</svg>
|
||||
<div class="container"><div class="overflow-label">{translation}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.bar {
|
||||
flex: 1 0 auto;
|
||||
position: relative;
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
|
||||
&__back {
|
||||
width: auto;
|
||||
padding: 1px 0.5px;
|
||||
height: calc(1.5rem + 2px);
|
||||
}
|
||||
&__element {
|
||||
fill: var(--accent-bg-color);
|
||||
stroke: var(--divider-color);
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
top: 0;
|
||||
left: 0.5rem;
|
||||
right: 0.5rem;
|
||||
min-width: 0;
|
||||
width: calc(100% - 1rem);
|
||||
height: 100%;
|
||||
font-weight: 500;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--dark-color);
|
||||
pointer-events: none;
|
||||
color: var(--caption-color);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -163,6 +163,7 @@ export { default as notificationsStore } from './components/notifications/store'
|
||||
export { NotificationPosition } from './components/notifications/NotificationPosition'
|
||||
export { NotificationSeverity } from './components/notifications/NotificationSeverity'
|
||||
export { Notification } from './components/notifications/Notification'
|
||||
export { default as Wizard } from './components/wizard/Wizard.svelte'
|
||||
|
||||
export * from './types'
|
||||
export * from './location'
|
||||
|
@ -281,3 +281,11 @@ export interface TimelineState {
|
||||
timelineBox: DOMRect
|
||||
viewBox: DOMRect
|
||||
}
|
||||
|
||||
export interface WizardModel {
|
||||
label: IntlString
|
||||
component: AnyComponent | AnySvelteComponent
|
||||
props?: any
|
||||
}
|
||||
export type WizardItemPosition = 'start' | 'middle' | 'end'
|
||||
export type WizardItemPositionState = 'current' | 'prev' | 'next'
|
||||
|
Loading…
Reference in New Issue
Block a user