This commit is contained in:
2025-12-22 10:53:15 +00:00
commit 753a98c67b
63 changed files with 15976 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
import { html } from '@design.estate/dees-element';
import { injectCssVariables } from '../../00variables.js';
export const demoFunc = () => {
injectCssVariables();
return html`
<style>
.demo-section {
margin-bottom: 2rem;
}
.demo-section h3 {
margin: 0 0 1rem 0;
font-size: 0.875rem;
color: var(--dees-muted-foreground);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.demo-note {
font-size: 0.875rem;
color: var(--dees-muted-foreground);
margin-top: 0.5rem;
}
</style>
<div class="demo-section">
<h3>Action Sheet</h3>
<dees-mobile-button
@click=${(e: Event) => {
const container = (e.target as HTMLElement).parentElement;
const existing = container?.querySelector('dees-mobile-actionsheet');
if (existing) existing.remove();
const sheet = document.createElement('dees-mobile-actionsheet');
(sheet as any).title = 'Add Photo';
(sheet as any).options = [
{
id: 'camera',
icon: 'camera',
iconColor: 'var(--dees-primary)',
iconBackground: 'rgba(59, 130, 246, 0.1)',
title: 'Take Photo',
subtitle: 'Use camera to capture a new photo'
},
{
id: 'gallery',
icon: 'image',
iconColor: '#16a34a',
iconBackground: '#dcfce7',
title: 'Choose from Gallery',
subtitle: 'Select an existing photo'
}
];
sheet.addEventListener('close', () => sheet.remove());
sheet.addEventListener('select', (ev: any) => {
console.log('Selected:', ev.detail);
sheet.remove();
});
document.body.appendChild(sheet);
}}
>Show Photo Options</dees-mobile-button>
<p class="demo-note">Opens an iOS-style action sheet from the bottom of the screen.</p>
</div>
<div class="demo-section">
<h3>Share Options</h3>
<dees-mobile-button
variant="outline"
@click=${(e: Event) => {
const sheet = document.createElement('dees-mobile-actionsheet');
(sheet as any).title = 'Share';
(sheet as any).options = [
{
id: 'copy',
icon: 'copy',
title: 'Copy Link'
},
{
id: 'email',
icon: 'mail',
title: 'Send via Email'
},
{
id: 'message',
icon: 'message-circle',
title: 'Send Message'
}
];
sheet.addEventListener('close', () => sheet.remove());
sheet.addEventListener('select', (ev: any) => {
console.log('Share via:', ev.detail);
sheet.remove();
});
document.body.appendChild(sheet);
}}
>Share Options</dees-mobile-button>
</div>
`;
};

View File

@@ -0,0 +1,223 @@
import {
DeesElement,
css,
cssManager,
customElement,
html,
property,
type TemplateResult,
} from '@design.estate/dees-element';
import { mobileComponentStyles } from '../../00componentstyles.js';
import '../dees-mobile-icon/dees-mobile-icon.js';
import { demoFunc } from './dees-mobile-actionsheet.demo.js';
export interface IActionSheetOption {
id: string;
icon?: string;
iconColor?: string;
iconBackground?: string;
title: string;
subtitle?: string;
}
declare global {
interface HTMLElementTagNameMap {
'dees-mobile-actionsheet': DeesMobileActionsheet;
}
}
@customElement('dees-mobile-actionsheet')
export class DeesMobileActionsheet extends DeesElement {
public static demo = demoFunc;
@property({ type: String })
accessor title: string = '';
@property({ type: Array })
accessor options: IActionSheetOption[] = [];
@property({ type: String })
accessor cancelText: string = 'Cancel';
public static styles = [
cssManager.defaultStyles,
mobileComponentStyles,
css`
:host {
position: fixed;
inset: 0;
z-index: var(--dees-z-modal, 500);
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.backdrop {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0);
animation: fadeInBackdrop 0.2s ease-out forwards;
}
@keyframes fadeInBackdrop {
to {
background: rgba(0, 0, 0, 0.5);
}
}
.sheet {
position: relative;
background: var(--dees-card);
border-radius: var(--dees-radius-lg) var(--dees-radius-lg) 0 0;
padding: var(--dees-space-md);
padding-bottom: calc(var(--dees-space-md) + env(safe-area-inset-bottom, 0px));
transform: translateY(100%);
animation: slideUp 0.3s ease-out forwards;
}
@keyframes slideUp {
to {
transform: translateY(0);
}
}
.sheet-title {
text-align: center;
font-size: 0.875rem;
color: var(--dees-muted-foreground);
margin-bottom: var(--dees-space-md);
padding-bottom: var(--dees-space-sm);
border-bottom: 1px solid var(--dees-border);
}
.options {
display: flex;
flex-direction: column;
gap: var(--dees-space-xs);
}
.option {
display: flex;
align-items: center;
gap: var(--dees-space-md);
padding: var(--dees-space-md);
border: none;
background: var(--dees-background);
border-radius: var(--dees-radius-md);
cursor: pointer;
color: var(--dees-foreground);
font-size: 1rem;
font-weight: 500;
text-align: left;
transition: background var(--dees-transition-fast);
}
.option:hover {
background: var(--dees-muted);
}
.option:active {
background: var(--dees-accent);
}
.option-icon {
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--dees-radius-full);
flex-shrink: 0;
background: var(--dees-accent);
color: var(--dees-primary);
}
.option-text {
flex: 1;
}
.option-title {
font-weight: 500;
}
.option-subtitle {
font-size: 0.75rem;
color: var(--dees-muted-foreground);
font-weight: normal;
margin-top: 2px;
}
.cancel {
margin-top: var(--dees-space-sm);
padding: var(--dees-space-md);
border: none;
background: var(--dees-background);
border-radius: var(--dees-radius-md);
cursor: pointer;
color: var(--dees-danger);
font-size: 1rem;
font-weight: 500;
width: 100%;
transition: background var(--dees-transition-fast);
}
.cancel:hover {
background: rgba(220, 38, 38, 0.1);
}
`,
];
private handleSelect(option: IActionSheetOption) {
this.dispatchEvent(new CustomEvent('select', {
detail: option,
bubbles: true,
composed: true,
}));
}
private handleClose() {
this.dispatchEvent(new CustomEvent('close', {
bubbles: true,
composed: true,
}));
}
public render(): TemplateResult {
return html`
<div class="backdrop" @click=${this.handleClose}></div>
<div class="sheet">
${this.title ? html`<div class="sheet-title">${this.title}</div>` : ''}
<div class="options">
${this.options.map(option => html`
<button class="option" @click=${() => this.handleSelect(option)}>
${option.icon ? html`
<div
class="option-icon"
style=${option.iconBackground ? `background: ${option.iconBackground}` : ''}
>
<dees-mobile-icon
icon=${option.icon}
size="24"
color=${option.iconColor || 'currentColor'}
></dees-mobile-icon>
</div>
` : ''}
<div class="option-text">
<div class="option-title">${option.title}</div>
${option.subtitle ? html`
<div class="option-subtitle">${option.subtitle}</div>
` : ''}
</div>
</button>
`)}
</div>
<button class="cancel" @click=${this.handleClose}>
${this.cancelText}
</button>
</div>
`;
}
}

View File

@@ -0,0 +1 @@
export * from './dees-mobile-actionsheet.js';