@operato/layout 8.0.0-beta.0 β†’ 8.0.0-beta.1

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/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [8.0.0-beta.1](https://github.com/hatiolab/operato/compare/v8.0.0-beta.0...v8.0.0-beta.1) (2025-01-08)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * missing .npmignore ([be05985](https://github.com/hatiolab/operato/commit/be05985abfae4af53501f718dd52932099f7fbcb))
12
+
13
+
14
+
6
15
  ## [8.0.0-beta.0](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.56...v8.0.0-beta.0) (2025-01-07)
7
16
 
8
17
  **Note:** Version bump only for package @operato/layout
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@operato/layout",
3
3
  "description": "Webcomponent layout following open-wc recommendations",
4
4
  "author": "heartyoh",
5
- "version": "8.0.0-beta.0",
5
+ "version": "8.0.0-beta.1",
6
6
  "main": "dist/src/index.js",
7
7
  "module": "dist/src/index.js",
8
8
  "exports": {
@@ -62,10 +62,10 @@
62
62
  },
63
63
  "dependencies": {
64
64
  "@material/web": "^2.0.0",
65
- "@operato/popup": "^8.0.0-beta.0",
66
- "@operato/shell": "^8.0.0-beta.0",
67
- "@operato/styles": "^8.0.0-beta.0",
68
- "@operato/utils": "^8.0.0-beta.0",
65
+ "@operato/popup": "^8.0.0-beta.1",
66
+ "@operato/shell": "^8.0.0-beta.1",
67
+ "@operato/styles": "^8.0.0-beta.1",
68
+ "@operato/utils": "^8.0.0-beta.1",
69
69
  "lit": "^3.1.2",
70
70
  "pwa-helpers": "^0.9.1"
71
71
  },
@@ -101,5 +101,5 @@
101
101
  "prettier --write"
102
102
  ]
103
103
  },
104
- "gitHead": "c4e9cc245659d050a9ffd66542083a6daad4bcb9"
104
+ "gitHead": "d5b28a2e9deb632c0dc80132f6a7196dd6fe4220"
105
105
  }
package/.editorconfig DELETED
@@ -1,29 +0,0 @@
1
- # EditorConfig helps developers define and maintain consistent
2
- # coding styles between different editors and IDEs
3
- # editorconfig.org
4
-
5
- root = true
6
-
7
-
8
- [*]
9
-
10
- # Change these settings to your own preference
11
- indent_style = space
12
- indent_size = 2
13
-
14
- # We recommend you to keep these unchanged
15
- end_of_line = lf
16
- charset = utf-8
17
- trim_trailing_whitespace = true
18
- insert_final_newline = true
19
-
20
- [*.md]
21
- trim_trailing_whitespace = false
22
-
23
- [*.json]
24
- indent_size = 2
25
-
26
- [*.{html,js,md}]
27
- block_comment_start = /**
28
- block_comment = *
29
- block_comment_end = */
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- stories: ['../dist/stories/**/*.stories.{js,md,mdx}'],
3
- };
@@ -1,52 +0,0 @@
1
- import { i18next } from '@operato/i18n'
2
-
3
- export const globalTypes = {
4
- locale: {
5
- name: 'Locale',
6
- description: 'Internationalization locale',
7
- toolbar: {
8
- icon: 'globe',
9
- items: [
10
- { value: 'en', right: 'πŸ‡ΊπŸ‡Έ', title: 'English' },
11
- { value: 'ko', right: 'πŸ‡°πŸ‡·', title: 'ν•œκ΅­μ–΄' },
12
- { value: 'zh', right: 'πŸ‡¨πŸ‡³', title: 'δΈ­ζ–‡' },
13
- { value: 'ja', right: 'πŸ‡―πŸ‡΅', title: 'ζ—₯本θͺž' },
14
- { value: 'ms', right: 'πŸ‡²πŸ‡Ύ', title: 'Bahasa Melayu' }
15
- ],
16
- showName: true
17
- }
18
- },
19
- theme: {
20
- name: 'Theme',
21
- description: 'Global theme for components',
22
- toolbar: {
23
- icon: 'paintbrush',
24
- items: [
25
- { value: 'light', title: 'Light' },
26
- { value: 'dark', title: 'Dark' }
27
- ],
28
- showName: true
29
- }
30
- }
31
- }
32
-
33
- export const decorators = [
34
- (Story, context) => {
35
- const { locale, theme } = context.globals
36
-
37
- if (locale) {
38
- i18next.changeLanguage(locale)
39
- }
40
-
41
- // Set the theme class for the document
42
- if (theme === 'dark') {
43
- document.documentElement.classList.add('dark')
44
- document.documentElement.classList.remove('light')
45
- } else {
46
- document.documentElement.classList.add('light')
47
- document.documentElement.classList.remove('dark')
48
- }
49
-
50
- return Story()
51
- }
52
- ]
@@ -1,8 +0,0 @@
1
- import { storybookPlugin } from '@web/dev-server-storybook';
2
- import baseConfig from '../web-dev-server.config.mjs';
3
-
4
- export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
5
- ...baseConfig,
6
- open: '/',
7
- plugins: [storybookPlugin({ type: 'web-components' }), ...baseConfig.plugins],
8
- });
@@ -1,222 +0,0 @@
1
- import { TemplateResult } from 'lit'
2
-
3
- import { PopupHandle, PopupOptions, setOpenPopupImplementation } from '@operato/popup'
4
- import { store } from '@operato/shell'
5
-
6
- export type Viewpart = {
7
- hovering?: 'center' | 'edge' | 'next'
8
- show?: boolean
9
- size?: string
10
- title?: string
11
- help?: string
12
- level?: VIEWPART_LEVEL
13
- closable?: boolean
14
- search?: {
15
- value?: string
16
- handler?: (closure: any, value: string) => void
17
- placeholder?: string
18
- }
19
- filter?: {
20
- handler?: (closure: any) => void
21
- }
22
- backdrop?: boolean
23
- temporary?: boolean /* auto remove */
24
- resizable?: boolean
25
- template?: TemplateResult
26
- position?: VIEWPART_POSITION
27
- templateProperties?: any
28
- zIndex?: number
29
- }
30
-
31
- export type AppendViewpartAction = {
32
- name: string
33
- viewpart: Viewpart
34
- position: VIEWPART_POSITION
35
- }
36
-
37
- export const appendViewpart = ({ name, viewpart, position }: AppendViewpartAction) => {
38
- store.dispatch({
39
- type: APPEND_VIEWPART,
40
- name,
41
- viewpart: {
42
- ...viewpart,
43
- show: viewpart.hovering && viewpart.show ? false : viewpart.show
44
- },
45
- position
46
- })
47
-
48
- if (viewpart.hovering && viewpart.show) {
49
- openOverlay(name)
50
- }
51
- }
52
-
53
- export const removeViewpart = (name: string) => {
54
- store.dispatch({
55
- type: REMOVE_VIEWPART,
56
- name
57
- })
58
- }
59
-
60
- export const updateViewpart = (name: string, override: any) => {
61
- store.dispatch({
62
- type: UPDATE_VIEWPART,
63
- name,
64
- override
65
- })
66
- }
67
-
68
- export const APPEND_VIEWPART = 'APPEND_VIEWPART'
69
- export const REMOVE_VIEWPART = 'REMOVE_VIEWPART'
70
- export const UPDATE_VIEWPART = 'UPDATE_VIEWPART'
71
-
72
- export enum VIEWPART_POSITION {
73
- HEADERBAR = 'headerbar',
74
- NAVBAR = 'navbar',
75
- ASIDEBAR = 'asidebar',
76
- FOOTERBAR = 'footerbar',
77
- PAGE_HEADERBAR = 'page-headerbar',
78
- PAGE_FOOTERBAR = 'page-footerbar'
79
- }
80
-
81
- /**
82
- * 각 뷰파트 μŠ€νƒμ˜ μˆœμ„œλ₯Ό μ •ν•˜λŠ” 속성이닀.
83
- * 뷰파트의 level 속성에 μ •μ˜λ˜λ„λ‘ ν•œλ‹€.
84
- * 맨 μœ„/μ•„λž˜/쒌츑/μš°μΈ‘μ— λ³΄μ—¬μ Έμ•Όν•˜λŠ” λ·°νŒŒνŠΈλŠ” TOPMOST 속성을 갖도둝 ν•˜κ³ ,
85
- * μŒ“μΈ μˆœμ„œλŒ€λ‘œ λ³΄μ—¬μ§€λŠ” λ·°νŒŒνŠΈλŠ” NORMAL 속성을 갖도둝 ν•œλ‹€.
86
- * default 속성은 NORMAL이닀.
87
- */
88
- export enum VIEWPART_LEVEL {
89
- TOPMOST = 'TOPMOST',
90
- NORMAL = 'NORMAL'
91
- }
92
-
93
- export enum TOOL_POSITION {
94
- FRONT_END = 'FRONT_END',
95
- FRONT = 'FRONT',
96
- CENTER = 'CENTER',
97
- REAR = 'REAR',
98
- REAR_END = 'REAR_END'
99
- }
100
-
101
- export const UPDATE_VIEWPORT_WIDTH = 'UPDATE_VIEWPORT_WIDTH'
102
-
103
- export const updateLayout = (wide?: boolean) => {
104
- store.dispatch({
105
- type: UPDATE_VIEWPORT_WIDTH,
106
- width: wide ? 'WIDE' : 'NARROW'
107
- })
108
- }
109
-
110
- /* overlay navigation */
111
- var overlaySequence = 0
112
-
113
- export const openOverlay = (name: string, options?: any, silent?: boolean) => {
114
- var beforeState = history.state
115
- var beforeOverlay = beforeState ? beforeState.overlay : undefined
116
- var beforeSequence = !beforeOverlay || beforeOverlay.sequence === undefined ? overlaySequence : beforeOverlay.sequence
117
- var afterSequence = (overlaySequence = beforeSequence + 1)
118
-
119
- /* store의 layout의 λ‚΄μš©μ„ λ³€κ²½ν•œλ‹€. */
120
- if (!silent && options) {
121
- store.dispatch({
122
- type: UPDATE_VIEWPART,
123
- name,
124
- override: options
125
- })
126
- }
127
-
128
- /*
129
- * ν˜„μž¬ history.stateλ₯Ό ν™•μΈν•˜κ³ , overlay의 이름이 같은
130
- * history에 μΆ”κ°€ν•˜κ³  open λ™μž‘μ„ μ‹€ν–‰ν•œλ‹€.
131
- */
132
- var afterState = Object.assign({}, beforeState || {}, {
133
- overlay: { name, sequence: afterSequence, escapable: options?.escapable !== false }
134
- })
135
-
136
- history.pushState(afterState, '', location.href)
137
-
138
- window.dispatchEvent(
139
- new CustomEvent('popstate', {
140
- detail: { state: afterState }
141
- })
142
- )
143
- }
144
-
145
- export const closeOverlay = (name: string) => {
146
- /*
147
- * μ‹€μ œλ‘œ overlayλ₯Ό closeν•˜λŠ” μž‘μ—…μ€ window.onpopstate ν•Έλ“€λŸ¬μ—μ„œ ν•œλ‹€.
148
- */
149
- history.back()
150
- }
151
-
152
- export const toggleOverlay = (name: string, options: any) => {
153
- var { name: beforeOverlayName } = (history.state && history.state.overlay) || {}
154
-
155
- if (beforeOverlayName == name) {
156
- closeOverlay(name)
157
- } else {
158
- openOverlay(name, options)
159
- }
160
- }
161
-
162
- /*
163
- * popup handling
164
- *
165
- * popup은 overlay의 νŠΉλ³„ν•œ ν˜•νƒœμ΄λ‹€.
166
- * popup은 open될 λ•Œ, viewpartλ₯Ό append ν•˜λ©°, close 될 λ•Œ viewpartλ₯Ό remove ν•œλ‹€.
167
- * - name: '$popup-${popupSequence}'
168
- * - position: VIEWPART_POSITION_HEADERBAR
169
- * - hovering: 'center' | 'next' | 'edge'
170
- */
171
- var popupSequence = 0
172
-
173
- /**
174
- * open popup in operato application environment
175
- *
176
- * @param {*} template html template to be rendered inside the popup
177
- * @param {PopupOptions} options
178
- * @returns popup handle object. This object is used to close the popup.
179
- */
180
- export const openPopup = (template: TemplateResult, options: PopupOptions = {}): PopupHandle => {
181
- var name = `$popup-${popupSequence++}`
182
-
183
- appendViewpart({
184
- name,
185
- viewpart: {
186
- hovering: 'center',
187
- closable: true,
188
- ...options,
189
- backdrop: true,
190
- show: false,
191
- temporary: true /* auto remove */,
192
- template
193
- },
194
- position: VIEWPART_POSITION.HEADERBAR
195
- })
196
-
197
- openOverlay(name, options, true)
198
-
199
- var popup = {
200
- name,
201
- close: () => {
202
- /* ν˜„μž¬ overlay stateλ₯Ό ν™•μΈν•΄μ„œ, μžμ‹ μΈ κ²½μš°μ— history.back() ν•œλ‹€. */
203
- var state = history.state
204
- var overlay = (state || {}).overlay
205
-
206
- overlay && overlay.name == name && history.back()
207
- },
208
- closed: false
209
- } as PopupHandle
210
-
211
- document.addEventListener('overlay-closed', function listener(e) {
212
- if (name == (e as CustomEvent).detail) {
213
- popup.closed = true
214
- popup.onclosed && popup.onclosed()
215
- document.removeEventListener('overlay-closed', listener)
216
- }
217
- })
218
-
219
- return popup
220
- }
221
-
222
- setOpenPopupImplementation(openPopup)
@@ -1,60 +0,0 @@
1
- import { Action } from 'redux'
2
-
3
- export const OPEN_SNACKBAR = 'OPEN_SNACKBAR'
4
- export const CLOSE_SNACKBAR = 'CLOSE_SNACKBAR'
5
-
6
- var snackbarTimer: number
7
-
8
- export type NotificationLevel = 'info' | 'warn' | 'error'
9
- export type Notification = {
10
- message: string
11
- level?: NotificationLevel
12
- option?: any
13
- ex?: any
14
- }
15
-
16
- export function notify(notification: string | Notification): void {
17
- if (typeof notification === 'string') {
18
- return notify({ message: notification })
19
- }
20
-
21
- var { message, level, option, ex } = notification as Notification
22
-
23
- document.dispatchEvent(
24
- new CustomEvent('notify', {
25
- detail: { message, level, ex, option }
26
- })
27
- )
28
- }
29
-
30
- export type SnackbarAction = {
31
- type: 'OPEN_SNACKBAR' | 'CLOSE_SNACKBAR'
32
- level?: NotificationLevel
33
- message?: string
34
- action?: any
35
- }
36
-
37
- export const showSnackbar =
38
- (
39
- level: NotificationLevel,
40
- {
41
- message,
42
- action,
43
- timer = 5000
44
- }: {
45
- message: string
46
- action?: any
47
- timer?: number
48
- }
49
- ) =>
50
- (dispatch: (param: SnackbarAction) => Action<any>) => {
51
- dispatch({
52
- type: OPEN_SNACKBAR,
53
- level,
54
- message,
55
- action
56
- })
57
- window.clearTimeout(snackbarTimer)
58
-
59
- if (timer != -1) snackbarTimer = window.setTimeout(() => dispatch({ type: CLOSE_SNACKBAR }), timer)
60
- }
@@ -1,137 +0,0 @@
1
- import { LitElement, css, html } from 'lit'
2
-
3
- import { customElement } from 'lit/decorators.js'
4
-
5
- @customElement('ox-resize-splitter')
6
- export class ResizeSplitter extends LitElement {
7
- static styles = css`
8
- :host {
9
- position: relative;
10
- opacity: 0.7;
11
- background-color: var(--splitter-background-color);
12
- }
13
-
14
- :host(:hover) {
15
- background-color: var(--splitter-hover-background-color);
16
- }
17
-
18
- div {
19
- position: absolute;
20
- width: 100%;
21
- height: 100%;
22
- }
23
- `
24
-
25
- private dragstart?: { x: number; y: number }
26
-
27
- connectedCallback() {
28
- super.connectedCallback()
29
-
30
- if (this.hasAttribute('vertical')) {
31
- this.style.width = '3px'
32
- this.style.height = '100%'
33
- this.style.cursor = 'col-resize'
34
- } else {
35
- this.style.width = '100%'
36
- this.style.height = '3px'
37
- this.style.cursor = 'row-resize'
38
- }
39
- }
40
-
41
- render() {
42
- return html` <div @mousedown=${(e: MouseEvent) => this.onMouseDown(e)}></div> `
43
- }
44
-
45
- // TODO onDrag μ΄λ²€νŠΈκ°€ 계속 λ°œμƒν•˜λ―€λ‘œ μ²˜λ¦¬ν•˜λŠ” μ„±λŠ₯ μ €ν•˜λ¨. κ·Έλž˜μ„œ throttling ν•˜λ„λ‘ 함
46
- _throttled(delay: number, fn: (...args: any) => void) {
47
- let lastCall = 0
48
- return function (...args: any) {
49
- const now = new Date().getTime()
50
- if (now - lastCall < delay) {
51
- return
52
- }
53
- lastCall = now
54
- return fn(...args)
55
- }
56
- }
57
-
58
- private onMouseDown(e: MouseEvent) {
59
- this.dragstart = {
60
- x: e.clientX,
61
- y: e.clientY
62
- }
63
-
64
- this.dispatchEvent(
65
- new CustomEvent('splitter-dragstart', {
66
- bubbles: true,
67
- composed: true
68
- })
69
- )
70
-
71
- window.addEventListener('mousemove', this.onMouseMoveHandler)
72
- window.addEventListener('mouseup', this.onMouseUpHandler)
73
-
74
- e.stopPropagation()
75
- }
76
-
77
- onMouseMoveHandler = this._throttled(100, this.onMouseMove.bind(this)) // this.onMouseMove.bind(this)
78
- onMouseUpHandler = this.onMouseUp.bind(this)
79
-
80
- private onMouseMove(e: MouseEvent) {
81
- if (!this.dragstart) {
82
- return
83
- }
84
-
85
- e.preventDefault()
86
-
87
- this.dispatchEvent(
88
- new CustomEvent('splitter-drag', {
89
- bubbles: true,
90
- composed: true,
91
- detail: {
92
- x: e.clientX - this.dragstart!.x,
93
- y: e.clientY - this.dragstart!.y
94
- }
95
- })
96
- )
97
- requestAnimationFrame(() => {
98
- dispatchEvent(new Event('resize'))
99
- })
100
-
101
- if (this.hasAttribute('vertical')) {
102
- document.body.style.cursor = 'col-resize'
103
- } else {
104
- document.body.style.cursor = 'row-resize'
105
- }
106
-
107
- document.body.style.userSelect = 'none'
108
-
109
- e.stopPropagation()
110
- }
111
-
112
- private onMouseUp(e: MouseEvent) {
113
- window.removeEventListener('mousemove', this.onMouseMoveHandler)
114
- window.removeEventListener('mouseup', this.onMouseUpHandler)
115
-
116
- this.dispatchEvent(
117
- new CustomEvent('splitter-dragend', {
118
- bubbles: true,
119
- composed: true,
120
- detail: {
121
- x: e.clientX - this.dragstart!.x,
122
- y: e.clientY - this.dragstart!.y
123
- }
124
- })
125
- )
126
-
127
- requestAnimationFrame(() => {
128
- dispatchEvent(new Event('resize'))
129
- delete this.dragstart
130
- })
131
-
132
- document.body.style.cursor = ''
133
- document.body.style.userSelect = ''
134
-
135
- e.stopPropagation()
136
- }
137
- }
@@ -1,113 +0,0 @@
1
- import { LitElement, html, css, PropertyValues, nothing } from 'lit'
2
- import { customElement, property, query } from 'lit/decorators.js'
3
-
4
- @customElement('ox-split-pane')
5
- export class OxSplitPane extends LitElement {
6
- static styles = css`
7
- :host {
8
- display: flex;
9
- flex-direction: var(--flex-direction, column);
10
-
11
- width: 100%;
12
- height: 100%;
13
- }
14
-
15
- #splitter {
16
- background-color: #ccc;
17
- cursor: var(--cursor-shape, col-resize);
18
- }
19
-
20
- #splitter {
21
- background-color: #ccc;
22
- cursor: var(--cursor-shape, col-resize);
23
- color: var(--md-sys-color-on-primary-container, #ccc);
24
- }
25
-
26
- :host([direction='row']) #splitter {
27
- height: 100%;
28
- width: 4px;
29
- }
30
-
31
- :host([direction='column']) #splitter {
32
- width: 100%;
33
- height: 4px;
34
- }
35
-
36
- ::slotted(*) {
37
- overflow: hidden;
38
- }
39
-
40
- slot[name='front']::slotted(*) {
41
- flex: var(--split-ratio, 0.5);
42
- }
43
-
44
- slot[name='back']::slotted(*) {
45
- flex: calc(1 - var(--split-ratio, 0.5));
46
- }
47
- `
48
-
49
- @property({ type: String, attribute: true }) direction: string = 'row'
50
- @property({ type: Number, attribute: true }) ratio: number = 0.5
51
- @property({ type: Boolean, attribute: true }) resizable: boolean = false
52
-
53
- @query('#splitter') splitter!: HTMLDivElement
54
-
55
- render() {
56
- return html`
57
- <slot name="front"></slot>
58
- ${this.resizable
59
- ? html`<div id="splitter" @mousedown=${this.startDragging} direction=${this.direction}></div>`
60
- : nothing}
61
- <slot name="back"></slot>
62
- `
63
- }
64
-
65
- async updated(changes: PropertyValues<this>) {
66
- if (changes.has('direction')) {
67
- this.style.setProperty('--flex-direction', this.direction)
68
- this.style.setProperty('--cursor-shape', this.direction == 'row' ? 'col-resize' : 'row-resize')
69
- }
70
-
71
- if (changes.has('ratio')) {
72
- this.style.setProperty('--split-ratio', String(this.ratio))
73
- }
74
- }
75
-
76
- startDragging(e: MouseEvent) {
77
- e.stopPropagation()
78
- e.preventDefault()
79
-
80
- document.addEventListener('mousemove', this.drag)
81
- document.addEventListener('mouseup', this.stopDragging)
82
-
83
- document.body.style.cursor = this.direction == 'row' ? 'col-resize' : 'row-resize'
84
- }
85
-
86
- drag = (e: MouseEvent) => {
87
- e.stopPropagation()
88
- e.preventDefault()
89
-
90
- const { width, height, left, top } = this.getBoundingClientRect()
91
-
92
- const mouseX = e.clientX - left
93
- const mouseY = e.clientY - top
94
-
95
- if (this.direction == 'row') {
96
- const totalWidth = this.offsetWidth
97
- this.ratio = mouseX / width
98
- } else {
99
- const totalHeight = this.offsetHeight
100
- this.ratio = mouseY / height
101
- }
102
- }
103
-
104
- stopDragging = (e: MouseEvent) => {
105
- e.stopPropagation()
106
- e.preventDefault()
107
-
108
- document.removeEventListener('mousemove', this.drag)
109
- document.removeEventListener('mouseup', this.stopDragging)
110
-
111
- document.body.style.cursor = 'auto'
112
- }
113
- }
package/src/index.ts DELETED
@@ -1,16 +0,0 @@
1
- import './initializer'
2
-
3
- export { PopupHandle, PopupOptions } from '@operato/popup'
4
-
5
- export * from './layouts/ox-snack-bar.js'
6
- export * from './layouts/ox-header-bar.js'
7
- export * from './layouts/ox-nav-bar.js'
8
- export * from './layouts/ox-aside-bar.js'
9
- export * from './layouts/ox-footer-bar.js'
10
- export * from './layouts/ox-page-header-bar.js'
11
- export * from './layouts/ox-page-footer-bar.js'
12
-
13
- export * from './actions/layout'
14
- export * from './actions/snackbar'
15
-
16
- export * from './components/ox-split-pane'