Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
4635e3fce5 | |||
af3dc5c466 | |||
12861b2230 | |||
b7f672e0f2 | |||
fcb44dfd24 | |||
f17b880b59 |
21
changelog.md
21
changelog.md
@ -1,5 +1,26 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-04-25 - 1.8.0 - feat(dees-pagination)
|
||||||
|
Add new pagination component to the library along with its demo and integration in the main export.
|
||||||
|
|
||||||
|
- Introduced dees-pagination component with support for various page range scenarios.
|
||||||
|
- Created demo file to showcase pagination with both small and large sets of pages.
|
||||||
|
- Updated the module's index to export the new pagination component.
|
||||||
|
|
||||||
|
## 2025-04-22 - 1.7.0 - feat(dees-searchbar)
|
||||||
|
Add dees-searchbar component with live search and filter demo
|
||||||
|
|
||||||
|
- Introduces a new dees-searchbar element with an input field, a search button, and filters
|
||||||
|
- Wires up events for 'search-changed' and 'search-submit' to provide real‐time feedback
|
||||||
|
- Adds a demo file to showcase usage and logging of search events
|
||||||
|
|
||||||
|
## 2025-04-22 - 1.6.0 - feat(documentation/dees-heading)
|
||||||
|
Add codex documentation overview and dees-heading component demo
|
||||||
|
|
||||||
|
- Introduce 'codex.md' to provide a high-level overview of project layout, component patterns, and build workflow
|
||||||
|
- Add and update dees-heading component with demo to support multiple heading levels and horizontal rule styles
|
||||||
|
- Update component export index to include dees-heading
|
||||||
|
|
||||||
## 2025-04-18 - 1.5.6 - fix(dependencies)
|
## 2025-04-18 - 1.5.6 - fix(dependencies)
|
||||||
Bump dependency versions and update demo code references
|
Bump dependency versions and update demo code references
|
||||||
|
|
||||||
|
43
codex.md
Normal file
43
codex.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Codex: Project Overview and Codebase Structure
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
- Package: `@design.estate/dees-catalog`
|
||||||
|
- Focus: Web Components library providing UI elements and layouts for modern web apps.
|
||||||
|
|
||||||
|
## Directory Layout
|
||||||
|
- ts_web/: TypeScript source files
|
||||||
|
- elements/: Individual Web Component definitions
|
||||||
|
- pages/: Page-level templates for composite layouts
|
||||||
|
- html/: Demo/app entry point loading the bundled scripts
|
||||||
|
- dist_bundle/: Bundled browser JS and source maps
|
||||||
|
- dist_ts_web/: ES module outputs for TypeScript/web consumers
|
||||||
|
- dist_watch/: Watch-mode development bundle with live reload
|
||||||
|
- test/: Browser-based tests using `@push.rocks/tapbundle`
|
||||||
|
|
||||||
|
## Component Patterns
|
||||||
|
- Each component in ts_web/elements/:
|
||||||
|
- Decorated with `@customElement('tag-name')`
|
||||||
|
- Extends `DeesElement` from `@design.estate/dees-element`
|
||||||
|
- Uses `@property` for reactive, reflected attributes
|
||||||
|
- Defines `static styles = [cssManager.defaultStyles, css`...`]`
|
||||||
|
- Implements `render()` returning a Lit `html` template with slots or markup
|
||||||
|
- Exposes a demo via `public static demo` linking to `.demo.ts` files
|
||||||
|
|
||||||
|
## Build & Development Workflow
|
||||||
|
- Install dependencies: `npm install` or `pnpm install`
|
||||||
|
- Build production bundle: `npm run build`
|
||||||
|
- Start dev watch mode: `npm run watch`
|
||||||
|
- Run tests: `npm test` (launches browser fixtures)
|
||||||
|
|
||||||
|
## Theming & Utilities
|
||||||
|
- Default global styles via `cssManager.defaultStyles`
|
||||||
|
- Theme-aware values with `cssManager.bdTheme(light, dark)`
|
||||||
|
- DOM utilities set up in `html/index.ts` using `@design.estate/dees-domtools`
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- `readme.md` provides an overview of all components and basic usage
|
||||||
|
- Live examples in `.demo.ts` files
|
||||||
|
accessible via component `demo` static property
|
||||||
|
|
||||||
|
## Updates to this file
|
||||||
|
If you have pattern insisights or general changes to the codebase, please update this file.
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@design.estate/dees-catalog",
|
"name": "@design.estate/dees-catalog",
|
||||||
"version": "1.5.6",
|
"version": "1.8.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
|
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
|
||||||
"main": "dist_ts_web/index.js",
|
"main": "dist_ts_web/index.js",
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@design.estate/dees-catalog',
|
name: '@design.estate/dees-catalog',
|
||||||
version: '1.5.6',
|
version: '1.8.0',
|
||||||
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
||||||
}
|
}
|
||||||
|
14
ts_web/elements/dees-heading.demo.ts
Normal file
14
ts_web/elements/dees-heading.demo.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { html } from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
export function demoFunc() {
|
||||||
|
return html`
|
||||||
|
<dees-heading level="1">This is a H1 heading</dees-heading>
|
||||||
|
<dees-heading level="2">This is a H2 heading</dees-heading>
|
||||||
|
<dees-heading level="3">This is a H3 heading</dees-heading>
|
||||||
|
<dees-heading level="4">This is a H4 heading</dees-heading>
|
||||||
|
<dees-heading level="5">This is a H5 heading</dees-heading>
|
||||||
|
<dees-heading level="6">This is a H6 heading</dees-heading>
|
||||||
|
<dees-heading level="hr">This is an hr heading</dees-heading>
|
||||||
|
<dees-heading level="hr-small">This is an hr small heading</dees-heading>
|
||||||
|
`;
|
||||||
|
}
|
115
ts_web/elements/dees-heading.ts
Normal file
115
ts_web/elements/dees-heading.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import {
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
css,
|
||||||
|
property,
|
||||||
|
cssManager,
|
||||||
|
type TemplateResult,
|
||||||
|
DeesElement,
|
||||||
|
type CSSResult,
|
||||||
|
} from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
import { demoFunc } from './dees-heading.demo.js';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'dees-heading': DeesHeading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement('dees-heading')
|
||||||
|
export class DeesHeading extends DeesElement {
|
||||||
|
// demo
|
||||||
|
public static demo = demoFunc;
|
||||||
|
|
||||||
|
// properties
|
||||||
|
/**
|
||||||
|
* Heading level: 1-6 for h1-h6, or 'hr' for horizontal rule style
|
||||||
|
*/
|
||||||
|
@property({ type: String, reflect: true })
|
||||||
|
public level: '1' | '2' | '3' | '4' | '5' | '6' | 'hr' | 'hr-small' = '1';
|
||||||
|
|
||||||
|
// STATIC STYLES
|
||||||
|
public static styles: CSSResult[] = [
|
||||||
|
cssManager.defaultStyles,
|
||||||
|
css`
|
||||||
|
/* Heading styles */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin: 16px 0 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||||
|
}
|
||||||
|
h1 { font-size: 32px; font-family: 'Cal Sans'; letter-spacing: 0.025em;}
|
||||||
|
h2 { font-size: 28px; }
|
||||||
|
h3 { font-size: 24px; }
|
||||||
|
h4 { font-size: 20px; }
|
||||||
|
h5 { font-size: 16px; }
|
||||||
|
h6 { font-size: 14px; }
|
||||||
|
/* Horizontal rule style heading */
|
||||||
|
.heading-hr {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
margin: 16px 0;
|
||||||
|
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||||
|
}
|
||||||
|
/* Fade lines toward and away from text for hr style */
|
||||||
|
.heading-hr::before {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
/* fade in toward center */
|
||||||
|
background: ${cssManager.bdTheme(
|
||||||
|
'linear-gradient(to right, transparent, #ccc)',
|
||||||
|
'linear-gradient(to right, transparent, #333)'
|
||||||
|
)};
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
.heading-hr::after {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
/* fade out away from center */
|
||||||
|
background: ${cssManager.bdTheme(
|
||||||
|
'linear-gradient(to right, #ccc, transparent)',
|
||||||
|
'linear-gradient(to right, #333, transparent)'
|
||||||
|
)};
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
/* Small hr variant with reduced margins */
|
||||||
|
.heading-hr.heading-hr-small {
|
||||||
|
margin: 8px 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.heading-hr.heading-hr-small::before,
|
||||||
|
.heading-hr.heading-hr-small::after {
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
// INSTANCE
|
||||||
|
public render(): TemplateResult {
|
||||||
|
switch (this.level) {
|
||||||
|
case '1':
|
||||||
|
return html`<h1><slot></slot></h1>`;
|
||||||
|
case '2':
|
||||||
|
return html`<h2><slot></slot></h2>`;
|
||||||
|
case '3':
|
||||||
|
return html`<h3><slot></slot></h3>`;
|
||||||
|
case '4':
|
||||||
|
return html`<h4><slot></slot></h4>`;
|
||||||
|
case '5':
|
||||||
|
return html`<h5><slot></slot></h5>`;
|
||||||
|
case '6':
|
||||||
|
return html`<h6><slot></slot></h6>`;
|
||||||
|
case 'hr':
|
||||||
|
return html`<div class="heading-hr"><slot></slot></div>`;
|
||||||
|
case 'hr-small':
|
||||||
|
return html`<div class="heading-hr heading-hr-small"><slot></slot></div>`;
|
||||||
|
default:
|
||||||
|
return html`<h1><slot></slot></h1>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
ts_web/elements/dees-pagination.demo.ts
Normal file
28
ts_web/elements/dees-pagination.demo.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { html } from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demo for dees-pagination component
|
||||||
|
*/
|
||||||
|
export const demoFunc = () => html`
|
||||||
|
<div style="display: flex; align-items: center; gap: 16px;">
|
||||||
|
<!-- Small set of pages -->
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 4px;">
|
||||||
|
<span>5 pages, starting at 1:</span>
|
||||||
|
<dees-pagination
|
||||||
|
.total=${5}
|
||||||
|
.page=${1}
|
||||||
|
@page-change=${(e: CustomEvent) => console.log('Page changed to', e.detail.page)}
|
||||||
|
></dees-pagination>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Larger set of pages -->
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 4px;">
|
||||||
|
<span>15 pages, starting at 8:</span>
|
||||||
|
<dees-pagination
|
||||||
|
.total=${15}
|
||||||
|
.page=${8}
|
||||||
|
@page-change=${(e: CustomEvent) => console.log('Page changed to', e.detail.page)}
|
||||||
|
></dees-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
133
ts_web/elements/dees-pagination.ts
Normal file
133
ts_web/elements/dees-pagination.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import { customElement, html, DeesElement, property, css, cssManager, type TemplateResult } from '@design.estate/dees-element';
|
||||||
|
import { demoFunc } from './dees-pagination.demo.js';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'dees-pagination': DeesPagination;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple pagination component.
|
||||||
|
* @fires page-change - Emitted when the page is changed. detail: { page: number }
|
||||||
|
*/
|
||||||
|
@customElement('dees-pagination')
|
||||||
|
export class DeesPagination extends DeesElement {
|
||||||
|
public static demo = demoFunc;
|
||||||
|
/** Current page (1-based) */
|
||||||
|
@property({ type: Number, reflect: true })
|
||||||
|
public page = 1;
|
||||||
|
|
||||||
|
/** Total number of pages */
|
||||||
|
@property({ type: Number, reflect: true })
|
||||||
|
public total = 1;
|
||||||
|
|
||||||
|
public static styles = [
|
||||||
|
cssManager.defaultStyles,
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
margin: 0 2px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
|
border-radius: 3px;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
button:hover:not(:disabled) {
|
||||||
|
background: ${cssManager.bdTheme('#eee', '#444')};
|
||||||
|
}
|
||||||
|
button:disabled {
|
||||||
|
cursor: default;
|
||||||
|
color: ${cssManager.bdTheme('#aaa', '#666')};
|
||||||
|
}
|
||||||
|
button.current {
|
||||||
|
background: #0050b9;
|
||||||
|
color: #fff;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
span.ellipsis {
|
||||||
|
margin: 0 4px;
|
||||||
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
|
||||||
|
private get pages(): (number | string)[] {
|
||||||
|
const pages: (number | string)[] = [];
|
||||||
|
const total = this.total;
|
||||||
|
const current = this.page;
|
||||||
|
if (total <= 7) {
|
||||||
|
for (let i = 1; i <= total; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pages.push(1);
|
||||||
|
if (current > 4) {
|
||||||
|
pages.push('...');
|
||||||
|
}
|
||||||
|
const start = Math.max(2, current - 2);
|
||||||
|
const end = Math.min(total - 1, current + 2);
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
if (current < total - 3) {
|
||||||
|
pages.push('...');
|
||||||
|
}
|
||||||
|
pages.push(total);
|
||||||
|
}
|
||||||
|
return pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<button
|
||||||
|
@click=${() => this.changePage(this.page - 1)}
|
||||||
|
?disabled=${this.page <= 1}
|
||||||
|
aria-label="Previous page"
|
||||||
|
>
|
||||||
|
‹
|
||||||
|
</button>
|
||||||
|
${this.pages.map((p) =>
|
||||||
|
p === '...'
|
||||||
|
? html`<span class="ellipsis">…</span>`
|
||||||
|
: html`
|
||||||
|
<button
|
||||||
|
class="${p === this.page ? 'current' : ''}"
|
||||||
|
@click=${() => this.changePage(p as number)}
|
||||||
|
?disabled=${p === this.page}
|
||||||
|
aria-label="Page ${p}"
|
||||||
|
>
|
||||||
|
${p}
|
||||||
|
</button>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
@click=${() => this.changePage(this.page + 1)}
|
||||||
|
?disabled=${this.page >= this.total}
|
||||||
|
aria-label="Next page"
|
||||||
|
>
|
||||||
|
›
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private changePage(newPage: number) {
|
||||||
|
if (newPage < 1 || newPage > this.total || newPage === this.page) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.page = newPage;
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent('page-change', {
|
||||||
|
detail: { page: this.page },
|
||||||
|
bubbles: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
46
ts_web/elements/dees-searchbar.demo.ts
Normal file
46
ts_web/elements/dees-searchbar.demo.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { html } from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
export const demoFunc = () => {
|
||||||
|
const onChanged = (e: CustomEvent) => {
|
||||||
|
// find the demo wrapper and update the 'changed' log inside it
|
||||||
|
const wrapper = (e.target as HTMLElement).closest('.demoWrapper');
|
||||||
|
const el = wrapper?.querySelector('#changed');
|
||||||
|
if (el) el.textContent = `search-changed: ${e.detail.value}`;
|
||||||
|
};
|
||||||
|
const onSubmit = (e: CustomEvent) => {
|
||||||
|
// find the demo wrapper and update the 'submitted' log inside it
|
||||||
|
const wrapper = (e.target as HTMLElement).closest('.demoWrapper');
|
||||||
|
const el = wrapper?.querySelector('#submitted');
|
||||||
|
if (el) el.textContent = `search-submit: ${e.detail.value}`;
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
.demoWrapper {
|
||||||
|
display: block;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
background: #888888;
|
||||||
|
}
|
||||||
|
.logs {
|
||||||
|
padding: 16px;
|
||||||
|
width: 600px;
|
||||||
|
color: #fff;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
.logs div {
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="demoWrapper">
|
||||||
|
<dees-searchbar
|
||||||
|
@search-changed=${onChanged}
|
||||||
|
@search-submit=${onSubmit}
|
||||||
|
></dees-searchbar>
|
||||||
|
<div class="logs">
|
||||||
|
<div id="changed">search-changed:</div>
|
||||||
|
<div id="submitted">search-submit:</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
160
ts_web/elements/dees-searchbar.ts
Normal file
160
ts_web/elements/dees-searchbar.ts
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import {
|
||||||
|
customElement,
|
||||||
|
DeesElement,
|
||||||
|
property,
|
||||||
|
html,
|
||||||
|
cssManager,
|
||||||
|
unsafeCSS,
|
||||||
|
css,
|
||||||
|
type TemplateResult,
|
||||||
|
domtools,
|
||||||
|
query,
|
||||||
|
} from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
import * as colors from './00colors.js';
|
||||||
|
import { demoFunc } from './dees-searchbar.demo.js';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'dees-searchbar': DeesSearchbar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement('dees-searchbar')
|
||||||
|
export class DeesSearchbar extends DeesElement {
|
||||||
|
// DEMO
|
||||||
|
public static demo = demoFunc;
|
||||||
|
|
||||||
|
// STATIC
|
||||||
|
public static styles = [
|
||||||
|
cssManager.defaultStyles,
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
padding: 40px;
|
||||||
|
font-family: Dees Sans;
|
||||||
|
display: block;
|
||||||
|
background: ${cssManager.bdTheme('#eeeeeb', '#000000')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchboxContainer {
|
||||||
|
position: relative;
|
||||||
|
margin: auto;
|
||||||
|
max-width: 800px;
|
||||||
|
background: ${cssManager.bdTheme('#00000015', '#ffffff15')};
|
||||||
|
--boxHeight: 60px;
|
||||||
|
height: var(--boxHeight);
|
||||||
|
border-radius: var(--boxHeight);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 140px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-top: 1px solid ${cssManager.bdTheme('#00000015', '#ffffff20')};
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
color: ${cssManager.bdTheme('#000000', '#eeeeeb')};
|
||||||
|
padding-left: 25px;
|
||||||
|
margin-right: -8px;
|
||||||
|
outline: none;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchButton {
|
||||||
|
--buttonPadding: 8px;
|
||||||
|
background: ${cssManager.bdTheme('#eeeeeb', '#000000')};
|
||||||
|
color: ${cssManager.bdTheme('#000000', '#eeeeeb')};
|
||||||
|
line-height: calc(var(--boxHeight) - (var(--buttonPadding) * 2));
|
||||||
|
border-radius: var(--boxHeight);
|
||||||
|
transform: scale(1) ;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
transition: transform 0.1s, background 0.1s;
|
||||||
|
margin-right: var(--buttonPadding);
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchButton:hover {
|
||||||
|
color: #fff;
|
||||||
|
background: ${cssManager.bdTheme(colors.bright.blue, colors.dark.blue)};
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchButton:active {
|
||||||
|
color: #fff;
|
||||||
|
background: ${cssManager.bdTheme(colors.bright.blueActive, colors.dark.blueActive)};
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filters {
|
||||||
|
margin: auto;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
|
||||||
|
// INSTANCE
|
||||||
|
|
||||||
|
@property()
|
||||||
|
public filters = [];
|
||||||
|
|
||||||
|
|
||||||
|
@query('input')
|
||||||
|
public searchInput!: HTMLInputElement;
|
||||||
|
@query('.searchButton')
|
||||||
|
public searchButton!: HTMLElement;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="searchboxContainer">
|
||||||
|
<input type="text" placeholder="Your Skills (e.g. TypeScript, Rust, Projectmanagement)" />
|
||||||
|
<div class="searchButton">Search -></div>
|
||||||
|
</div>
|
||||||
|
${this.filters.length > 0 ? html`
|
||||||
|
<div class="filters">
|
||||||
|
<dees-heading level="hr-small">Filters</dees-heading>
|
||||||
|
<dees-input-dropdown .label=${'location'}></dees-input-dropdown>
|
||||||
|
</div>
|
||||||
|
` : html``}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Lifecycle: after first render, wire up events for input and submit actions
|
||||||
|
*/
|
||||||
|
public firstUpdated(): void {
|
||||||
|
// dispatch change on each input
|
||||||
|
this.searchInput.addEventListener('input', () => {
|
||||||
|
this.dispatchEvent(new CustomEvent('search-changed', {
|
||||||
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
detail: { value: this.searchInput.value }
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
// submit on Enter key
|
||||||
|
this.searchInput.addEventListener('keydown', (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
this._dispatchSubmit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// submit on button click
|
||||||
|
this.searchButton.addEventListener('click', () => this._dispatchSubmit());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch a submit event with the current search value
|
||||||
|
*/
|
||||||
|
private _dispatchSubmit(): void {
|
||||||
|
this.dispatchEvent(new CustomEvent('search-submit', {
|
||||||
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
detail: { value: this.searchInput.value }
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ export * from './dees-editor-markdown.js';
|
|||||||
export * from './dees-editor-markdownoutlet.js';
|
export * from './dees-editor-markdownoutlet.js';
|
||||||
export * from './dees-form-submit.js';
|
export * from './dees-form-submit.js';
|
||||||
export * from './dees-form.js';
|
export * from './dees-form.js';
|
||||||
|
export * from './dees-heading.js';
|
||||||
export * from './dees-hint.js';
|
export * from './dees-hint.js';
|
||||||
export * from './dees-icon.js';
|
export * from './dees-icon.js';
|
||||||
export * from './dees-input-checkbox.js';
|
export * from './dees-input-checkbox.js';
|
||||||
@ -35,6 +36,7 @@ export * from './dees-mobilenavigation.js';
|
|||||||
export * from './dees-modal.js';
|
export * from './dees-modal.js';
|
||||||
export * from './dees-input-multitoggle.js';
|
export * from './dees-input-multitoggle.js';
|
||||||
export * from './dees-pdf.js';
|
export * from './dees-pdf.js';
|
||||||
|
export * from './dees-searchbar.js';
|
||||||
export * from './dees-simple-appdash.js';
|
export * from './dees-simple-appdash.js';
|
||||||
export * from './dees-simple-login.js';
|
export * from './dees-simple-login.js';
|
||||||
export * from './dees-speechbubble.js';
|
export * from './dees-speechbubble.js';
|
||||||
@ -46,3 +48,4 @@ export * from './dees-toast.js';
|
|||||||
export * from './dees-updater.js';
|
export * from './dees-updater.js';
|
||||||
export * from './dees-windowcontrols.js';
|
export * from './dees-windowcontrols.js';
|
||||||
export * from './dees-windowlayer.js';
|
export * from './dees-windowlayer.js';
|
||||||
|
export * from './dees-pagination.js';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user