|
| 1 | +import {GecutDirective} from '@gecut/lit-helper/directives/directive.js'; |
| 2 | +import {noChange, nothing, html} from 'lit/html.js'; |
| 3 | +import {type PartInfo, directive} from 'lit/directive.js'; |
| 4 | +import {gecutButton, type ButtonContent} from '../button/button.js'; |
| 5 | +import {gecutIconButton, type IconButtonContent} from '../components.js'; |
| 6 | +import {classMap, type ClassInfo} from 'lit/directives/class-map.js'; |
| 7 | + |
| 8 | +export interface SnackBarContent { |
| 9 | + message: string; |
| 10 | + |
| 11 | + action?: Omit<ButtonContent, 'type'>; |
| 12 | + close?: boolean | Omit<IconButtonContent, 'type'>; |
| 13 | +} |
| 14 | + |
| 15 | +export class GecutSnackBarDirective extends GecutDirective { |
| 16 | + constructor(partInfo: PartInfo) { |
| 17 | + super(partInfo, 'gecut-snack-bar'); |
| 18 | + } |
| 19 | + |
| 20 | + protected content?: SnackBarContent; |
| 21 | + |
| 22 | + render(content?: SnackBarContent): unknown { |
| 23 | + this.log.methodArgs?.('render', content); |
| 24 | + |
| 25 | + if (content === undefined) return noChange; |
| 26 | + |
| 27 | + this.content = content; |
| 28 | + |
| 29 | + return this.renderSnackBar(); |
| 30 | + } |
| 31 | + |
| 32 | + protected renderSnackBar() { |
| 33 | + if (!this.content) return nothing; |
| 34 | + |
| 35 | + this.log.method?.('renderSnackBar'); |
| 36 | + |
| 37 | + return html` |
| 38 | + <div class=${classMap(this.getRenderClasses())}> |
| 39 | + <span class="gecut-snack-bar-message">${this.content.message}</span> |
| 40 | + ${this.renderAction()} ${this.renderClose()} |
| 41 | + </div> |
| 42 | + `; |
| 43 | + } |
| 44 | + protected renderAction(): unknown { |
| 45 | + if (!this.content?.action) return nothing; |
| 46 | + |
| 47 | + this.log.method?.('renderAction'); |
| 48 | + |
| 49 | + return gecutButton({...this.content.action, type: 'text'}); |
| 50 | + } |
| 51 | + protected renderClose(): unknown { |
| 52 | + if (!this.content?.close) return nothing; |
| 53 | + |
| 54 | + this.log.method?.('renderClose'); |
| 55 | + |
| 56 | + return gecutIconButton({ |
| 57 | + svg: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-dasharray="12" stroke-dashoffset="12" stroke-linecap="round" stroke-width="2" d="M12 12L19 19M12 12L5 5M12 12L5 19M12 12L19 5"><animate fill="freeze" attributeName="stroke-dashoffset" dur="1.2s" values="12;0"/></path></svg>', |
| 58 | + |
| 59 | + ...(typeof this.content.close !== 'boolean' ? this.content.close : {}), |
| 60 | + }); |
| 61 | + } |
| 62 | + |
| 63 | + protected override getRenderClasses(): ClassInfo { |
| 64 | + return { |
| 65 | + ...super.getRenderClasses(), |
| 66 | + |
| 67 | + 'longer-action': (this.content?.action?.label?.length ?? 0) > 10, |
| 68 | + }; |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +export const gecutSnackBar = directive(GecutSnackBarDirective); |
0 commit comments