diff --git a/.stylelintrc.cjs b/.stylelintrc.cjs index 99ff09b8f..497259778 100644 --- a/.stylelintrc.cjs +++ b/.stylelintrc.cjs @@ -40,11 +40,6 @@ module.exports = { files: ['blocks/**/*.css', 'solutions/**/*.css'], ignoreFiles: ['**/test/**/*.css'], plugins: ['./stylelint-force-app-name-prefix.cjs'], - rules: { - 'plugin/stylelint-force-app-name-prefix': { - appName: 'lr', - }, - }, }, ], }; diff --git a/CHANGELOG.md b/CHANGELOG.md index a36b0c793..4d9b39101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,34 @@ +# [0.46.0](https://github.com/uploadcare/blocks/compare/v0.45.0...v0.46.0) (2024-06-24) + +### Features + +- Significant improvements to accessibility and keyboard navigation, enhancing user experience and inclusivity ([#671](https://github.com/uploadcare/blocks/issues/671)) ([4acb8a0](https://github.com/uploadcare/blocks/commit/4acb8a0b7ea9c7a95be415627f7d4e1eb748fcf2)) + +# [0.45.0](https://github.com/uploadcare/blocks/compare/v0.44.0...v0.45.0) (2024-06-23) + +### BEAKING CHANGES + +- The previously deprecated API method `setUploadMetadata` has been removed. Use `metadata` instance property on `lr-config` block instead. See [metadata](https://uploadcare.com/docs/file-uploader/options/#metadata) for more details. +- The previously deprecated API method `addFiles` has been removed. Use `addFileFromObject`, `addFileFromUrl` or `addFileFromUuid` instead. See [File Uploader API](https://uploadcare.com/docs/file-uploader/api/#add-file-from-object) for more details. + +See the [migration guide](https://uploadcare.com/docs/file-uploader/migration-to-0.45.0/) for details. + +# [0.44.0](https://github.com/uploadcare/blocks/compare/v0.43.0...v0.44.0) (2024-06-21) + +### BEAKING CHANGES + +- All theme variables of the previous version are deprecated and won't affect the look anymore. +- The default button that opens the uploader dialog (SimpleBtn) component now uses independent variables. +- By default, the theme now uses OKLCH color space. You can still override it using other color spaces, but we recommend converting your colors to OKLCH. + +See the [migration guide](https://uploadcare.com/docs/file-uploader/migration-to-0.44.0/) for details. + +Full styling docs are available [here](https://uploadcare.com/docs/file-uploader/styling/). + +### Features + +- updated theming mechanics with oklch colors and reworked css properties ([#662](https://github.com/uploadcare/blocks/issues/662)) ([ee90e66](https://github.com/uploadcare/blocks/commit/ee90e66c076e21e1ee92b2f4c60f8eb955a7d5bc)) + # [0.43.0](https://github.com/uploadcare/blocks/compare/v0.42.1...v0.43.0) (2024-06-14) ### Features diff --git a/README.md b/README.md index 81d4d5a66..ec138ac17 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ and [even more](<(https://uploadcare.com/features/?ref=github-readme)>). See Uploadcare Blocks [in action](https://codesandbox.io/p/devbox/github/uploadcare/blocks-examples/tree/main/examples/js-uploader)! - + ## Core features diff --git a/abstract/ActivityBlock.js b/abstract/ActivityBlock.js index 7e6b742bf..6878ed45e 100644 --- a/abstract/ActivityBlock.js +++ b/abstract/ActivityBlock.js @@ -1,6 +1,6 @@ -import { EventType } from '../blocks/UploadCtxProvider/EventEmitter.js'; // @ts-check import { debounce } from '../blocks/utils/debounce.js'; +import { EventType } from '../blocks/UploadCtxProvider/EventEmitter.js'; import { Block } from './Block.js'; import { activityBlockCtx } from './CTX.js'; @@ -15,7 +15,7 @@ export class ActivityBlock extends Block { /** @private */ _deactivate() { - const actDesc = ActivityBlock._activityCallbacks.get(this); + let actDesc = ActivityBlock._activityCallbacks.get(this); this[ACTIVE_PROP] = false; this.removeAttribute(ACTIVE_ATTR); actDesc?.deactivateCallback?.(); @@ -23,7 +23,7 @@ export class ActivityBlock extends Block { /** @private */ _activate() { - const actDesc = ActivityBlock._activityCallbacks.get(this); + let actDesc = ActivityBlock._activityCallbacks.get(this); this.$['*historyBack'] = this.historyBack.bind(this); /** @private */ this[ACTIVE_PROP] = true; @@ -138,9 +138,7 @@ export class ActivityBlock extends Block { /** @type {string | null} */ const currentActivity = this.$['*currentActivity']; - /** @type {Set} */ - const blocksRegistry = this.$['*blocksRegistry']; - const hasCurrentActivityInCtx = !![...blocksRegistry].find( + const hasCurrentActivityInCtx = !![...this.blocksRegistry].find( (block) => block instanceof ActivityBlock && block.activityType === currentActivity, ); @@ -169,7 +167,7 @@ export class ActivityBlock extends Block { historyBack() { /** @type {String[]} */ - const history = this.$['*history']; + let history = this.$['*history']; if (history) { let nextActivity = history.pop(); while (nextActivity === this.activityType) { @@ -177,10 +175,8 @@ export class ActivityBlock extends Block { } let couldOpenActivity = !!nextActivity; if (nextActivity) { - /** @type {Set} */ - const blocksRegistry = this.$['*blocksRegistry']; - const nextActivityBlock = [...blocksRegistry].find((block) => block.activityType === nextActivity); - couldOpenActivity = nextActivityBlock?.couldOpenActivity ?? false; + const nextActivityBlock = [...this.blocksRegistry].find((block) => block.activityType === nextActivity); + couldOpenActivity = /** @type {ActivityBlock} */ (nextActivityBlock)?.couldOpenActivity ?? false; } nextActivity = couldOpenActivity ? nextActivity : undefined; this.$['*currentActivity'] = nextActivity; @@ -198,7 +194,6 @@ ActivityBlock.activities = Object.freeze({ DRAW: 'draw', UPLOAD_LIST: 'upload-list', URL: 'url', - CONFIRMATION: 'confirmation', CLOUD_IMG_EDIT: 'cloud-image-edit', EXTERNAL: 'external', DETAILS: 'details', diff --git a/abstract/Block.js b/abstract/Block.js index 44e68d399..f4e68c554 100644 --- a/abstract/Block.js +++ b/abstract/Block.js @@ -3,7 +3,7 @@ import { BaseComponent, Data } from '@symbiotejs/symbiote'; import { initialConfig } from '../blocks/Config/initialConfig.js'; import { EventEmitter } from '../blocks/UploadCtxProvider/EventEmitter.js'; import { WindowHeightTracker } from '../utils/WindowHeightTracker.js'; -import { extractCdnUrlModifiers, extractFilename, extractUuid } from '../utils/cdn-utils.js'; +import { extractFilename, extractCdnUrlModifiers, extractUuid } from '../utils/cdn-utils.js'; import { getLocaleDirection } from '../utils/getLocaleDirection.js'; import { getPluralForm } from '../utils/getPluralForm.js'; import { applyTemplateData, getPluralObjects } from '../utils/template-utils.js'; @@ -12,6 +12,7 @@ import { blockCtx } from './CTX.js'; import { LocaleManager, localeStateKey } from './LocaleManager.js'; import { l10nProcessor } from './l10nProcessor.js'; import { sharedConfigKey } from './sharedConfigKey.js'; +import { A11y } from './a11y.js'; const TAG_PREFIX = 'lr-'; @@ -19,7 +20,9 @@ const TAG_PREFIX = 'lr-'; export class Block extends BaseComponent { /** @type {string | null} */ static StateConsumerScope = null; - static className = ''; + + /** @type {string[]} */ + static styleAttrs = []; requireCtxName = false; allowCustomTemplate = true; /** @type {import('./ActivityBlock.js').ActivityType} */ @@ -36,15 +39,15 @@ export class Block extends BaseComponent { if (!str) { return ''; } - const template = this.$[localeStateKey(str)] || str; - const pluralObjects = getPluralObjects(template); - for (const pluralObject of pluralObjects) { + let template = this.$[localeStateKey(str)] || str; + let pluralObjects = getPluralObjects(template); + for (let pluralObject of pluralObjects) { variables[pluralObject.variable] = this.pluralize( pluralObject.pluralKey, Number(variables[pluralObject.countVariable]), ); } - const result = applyTemplateData(template, variables); + let result = applyTemplateData(template, variables); return result; } @@ -94,10 +97,7 @@ export class Block extends BaseComponent { * @returns {Boolean} */ hasBlockInCtx(callback) { - // @ts-ignore TODO: fix this - /** @type {Set} */ - const blocksRegistry = this.$['*blocksRegistry']; - for (const block of blocksRegistry) { + for (let block of this.blocksRegistry) { if (callback(block)) { return true; } @@ -128,14 +128,14 @@ export class Block extends BaseComponent { } connectedCallback() { - const className = /** @type {typeof Block} */ (this.constructor).className; - if (className) { - this.classList.toggle(`${TAG_PREFIX}${className}`, true); - } + const styleAttrs = /** @type {typeof Block} */ (this.constructor).styleAttrs; + styleAttrs.forEach((attr) => { + this.setAttribute(attr, ''); + }); if (this.hasAttribute('retpl')) { // @ts-ignore TODO: fix this - this.constructor.template = null; + this.constructor['template'] = null; this.processInnerHtml = true; } if (this.requireCtxName) { @@ -168,7 +168,7 @@ export class Block extends BaseComponent { this.add('*blocksRegistry', new Set()); } - const blocksRegistry = this.$['*blocksRegistry']; + let blocksRegistry = this.$['*blocksRegistry']; blocksRegistry.add(this); if (!this.has('*eventEmitter')) { @@ -178,8 +178,13 @@ export class Block extends BaseComponent { this.add('*localeManager', new LocaleManager(this)); } + if (!this.has('*a11y')) { + this.add('*a11y', new A11y()); + } + this.sub(localeStateKey('locale-id'), (localeId) => { - this.style.direction = getLocaleDirection(localeId); + const direction = getLocaleDirection(localeId); + this.style.direction = direction === 'ltr' ? '' : direction; }); } @@ -188,9 +193,18 @@ export class Block extends BaseComponent { return this.has('*localeManager') ? this.$['*localeManager'] : null; } + /** @returns {A11y | null} */ + get a11y() { + return this.has('*a11y') ? this.$['*a11y'] : null; + } + + /** @type {Set} */ + get blocksRegistry() { + return this.$['*blocksRegistry']; + } + destroyCallback() { - /** @type {Set} */ - const blocksRegistry = this.$['*blocksRegistry']; + let blocksRegistry = this.blocksRegistry; blocksRegistry.delete(this); this.localeManager?.destroyL10nBindings(this); @@ -217,6 +231,7 @@ export class Block extends BaseComponent { Data.deleteCtx(this.ctxName); this.localeManager?.destroy(); + this.a11y?.destroy(); } /** @@ -224,7 +239,7 @@ export class Block extends BaseComponent { * @param {Number} [decimals] */ fileSizeFmt(bytes, decimals = 2) { - const units = ['B', 'KB', 'MB', 'GB', 'TB']; + let units = ['B', 'KB', 'MB', 'GB', 'TB']; /** * @param {String} str * @returns {String} @@ -232,10 +247,10 @@ export class Block extends BaseComponent { if (bytes === 0) { return `0 ${units[0]}`; } - const k = 1024; - const dm = decimals < 0 ? 0 : decimals; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${units[i]}`; + let k = 1024; + let dm = decimals < 0 ? 0 : decimals; + let i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / k ** i).toFixed(dm)) + ' ' + units[i]; } /** @@ -268,7 +283,7 @@ export class Block extends BaseComponent { /** @returns {import('../types').ConfigType} } */ get cfg() { if (!this.__cfgProxy) { - const o = Object.create(null); + let o = Object.create(null); /** @private */ this.__cfgProxy = new Proxy(o, { set: (obj, key, value) => { @@ -327,10 +342,10 @@ export class Block extends BaseComponent { /** @param {String} [name] */ static reg(name) { if (!name) { - Block.reg(); + super.reg(); return; } - Block.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name); + super.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name); } } diff --git a/abstract/CTX.js b/abstract/CTX.js index fd349d240..520a8abc7 100644 --- a/abstract/CTX.js +++ b/abstract/CTX.js @@ -24,7 +24,6 @@ export const uploaderBlockCtx = (fnCtx) => ({ '*commonProgress': 0, '*uploadList': [], '*focusedEntry': null, - '*uploadMetadata': null, '*uploadQueue': new Queue(1), '*uploadCollection': null, /** @type {ReturnType[]} */ diff --git a/abstract/SolutionBlock.js b/abstract/SolutionBlock.js index 112ed3dd2..f9c883587 100644 --- a/abstract/SolutionBlock.js +++ b/abstract/SolutionBlock.js @@ -3,10 +3,16 @@ import { Block } from './Block.js'; import { uploaderBlockCtx } from './CTX.js'; export class SolutionBlock extends Block { + static styleAttrs = ['lr-wgt-common']; requireCtxName = true; init$ = uploaderBlockCtx(this); _template = null; + initCallback() { + super.initCallback(); + this.a11y?.registerBlock(this); + } + static set template(value) { SolutionBlock._template = `${svgIconsSprite + value}`; } diff --git a/abstract/UploaderBlock.js b/abstract/UploaderBlock.js index ed7efbb72..0aff20aa7 100644 --- a/abstract/UploaderBlock.js +++ b/abstract/UploaderBlock.js @@ -14,7 +14,6 @@ import { createCdnUrl, createCdnUrlModifiers } from '../utils/cdn-utils.js'; import { IMAGE_ACCEPT_LIST, fileIsImage, mergeFileTypes } from '../utils/fileTypes.js'; import { parseCdnUrl } from '../utils/parseCdnUrl.js'; import { stringToArray } from '../utils/stringToArray.js'; -import { warnOnce } from '../utils/warnOnce.js'; import { uploaderBlockCtx } from './CTX.js'; import { SecureUploadsManager } from './SecureUploadsManager.js'; import { TypedCollection } from './TypedCollection.js'; @@ -28,32 +27,6 @@ export class UploaderBlock extends ActivityBlock { init$ = uploaderBlockCtx(this); - /** @private */ - __initialUploadMetadata = null; - - /** - * This is Public JS API method. Could be called before block initialization, so we need to delay state interactions - * until block init. - * - * TODO: If we add more public methods, it is better to use the single queue instead of tons of private fields per - * each method. See https://github.com/uploadcare/blocks/pull/162/ - * - * @deprecated Use `metadata` instance property on `lr-config` block instead. - * @param {import('@uploadcare/upload-client').Metadata} metadata - * @public - */ - setUploadMetadata(metadata) { - warnOnce( - 'setUploadMetadata is deprecated. Use `metadata` instance property on `lr-config` block instead. See migration guide: https://uploadcare.com/docs/file-uploader/migration-to-0.25.0/', - ); - if (!this.connectedOnce) { - // @ts-ignore TODO: fix this - this.__initialUploadMetadata = metadata; - } else { - this.$['*uploadMetadata'] = metadata; - } - } - get hasCtxOwner() { return this.hasBlockInCtx((block) => { if (block instanceof UploaderBlock) { @@ -112,10 +85,6 @@ export class UploaderBlock extends ActivityBlock { this.$['*uploadQueue'].concurrency = Number(value) || 1; }); - if (this.__initialUploadMetadata) { - this.$['*uploadMetadata'] = this.__initialUploadMetadata; - } - if (!this.$['*secureUploadsManager']) { this.$['*secureUploadsManager'] = new SecureUploadsManager(this); } @@ -193,28 +162,6 @@ export class UploaderBlock extends ActivityBlock { return this.getOutputItem(internalId); } - /** - * @deprecated Will be removed in the near future. Please use `addFileFromObject`, `addFileFromUrl` or - * `addFileFromUuid` instead. - * @param {File[]} files - * @returns {import('../types').OutputFileEntry<'idle'>[]} - */ - addFiles(files) { - console.warn( - '`addFiles` method is deprecated. Please use `addFileFromObject`, `addFileFromUrl` or `addFileFromUuid` instead.', - ); - return files.map((/** @type {File} */ file) => { - const internalId = this.uploadCollection.add({ - file, - isImage: fileIsImage(file), - mimeType: file.type, - fileName: file.name, - fileSize: file.size, - }); - return this.getOutputItem(internalId); - }); - } - /** @param {string} internalId */ removeFileByInternalId(internalId) { if (!this.uploadCollection.read(internalId)) { @@ -311,8 +258,7 @@ export class UploaderBlock extends ActivityBlock { return; } - /** @type {Set} */ - const blocksRegistry = this.$['*blocksRegistry']; + const blocksRegistry = this.blocksRegistry; /** * @param {import('./Block').Block} block * @returns {block is import('../blocks/SourceBtn/SourceBtn.js').SourceBtn} @@ -586,7 +532,7 @@ export class UploaderBlock extends ActivityBlock { * @protected */ async getMetadataFor(entryId) { - const configValue = this.cfg.metadata ?? /** @type {import('../types').Metadata} */ (this.$['*uploadMetadata']); + const configValue = this.cfg.metadata || undefined; if (typeof configValue === 'function') { const outputFileEntry = this.getOutputItem(entryId); const metadata = await configValue(outputFileEntry); diff --git a/abstract/a11y.js b/abstract/a11y.js new file mode 100644 index 000000000..f29f1dce6 --- /dev/null +++ b/abstract/a11y.js @@ -0,0 +1,118 @@ +// @ts-check +import { startKeyUX, hiddenKeyUX, jumpKeyUX, focusGroupKeyUX, pressKeyUX } from 'keyux'; + +/** + * MinimalWindow interface is not exported by keyux, so we import it here using tricky way. + * + * @typedef {Parameters[0]} MinimalWindow + */ + +/** + * This is global window wrapper that allows to scope event listeners to a specific part of the DOM. + * + * It is used to scope the key UX to the widget. + * + * @implements {MinimalWindow} + */ +class ScopedMinimalWindow { + /** + * @private + * @type {Map void>} + */ + _listeners = new Map(); + + /** + * @private + * @type {Node[]} + */ + _scope = []; + + /** + * @param {'keydown' | 'keyup'} type + * @param {(event: Event) => void} listener + */ + addEventListener(type, listener) { + /** @param {Event} e */ + const wrappedListener = (e) => { + const target = e.target; + if (!target) return; + if (this._scope.some((el) => el === e.target || el.contains(/** @type {Node} */ (target)))) { + listener(e); + } + }; + this._listeners.set(listener, wrappedListener); + window.addEventListener(type, wrappedListener); + } + + /** + * @param {'keydown' | 'keyup'} type + * @param {(event: {}) => void} listener + */ + removeEventListener(type, listener) { + const wrappedListener = this._listeners.get(listener); + if (wrappedListener) { + window.removeEventListener(type, wrappedListener); + } + this._listeners.delete(listener); + } + + get CustomEvent() { + return window.CustomEvent; + } + + get document() { + return window.document; + } + + get navigator() { + return window.navigator; + } + + /** @param {Node} scope */ + registerScope(scope) { + this._scope.push(scope); + } + + destroy() { + this._scope = []; + this._listeners.forEach((listener, originalListener) => { + window.removeEventListener('keydown', listener); + window.removeEventListener('keyup', listener); + this._listeners.delete(originalListener); + }); + } +} + +export class A11y { + /** + * @private + * @type {(() => void) | undefined} + */ + _destroyKeyUX; + + /** + * @private + * @type {ScopedMinimalWindow} + */ + _scopedWindow; + + constructor() { + this._scopedWindow = new ScopedMinimalWindow(); + this._destroyKeyUX = startKeyUX(this._scopedWindow, [ + focusGroupKeyUX(), + pressKeyUX('is-pressed'), + jumpKeyUX(), + hiddenKeyUX(), + ]); + } + + /** @param {import('./Block.js').Block} scope */ + registerBlock(scope) { + this._scopedWindow.registerScope(scope); + } + + destroy() { + this._destroyKeyUX?.(); + this._scopedWindow.destroy(); + } +} diff --git a/blocks/ActivityHeader/activity-header.css b/blocks/ActivityHeader/activity-header.css index 50a236602..94f19bf92 100644 --- a/blocks/ActivityHeader/activity-header.css +++ b/blocks/ActivityHeader/activity-header.css @@ -1,34 +1,14 @@ lr-activity-header { display: flex; - gap: var(--gap-mid); justify-content: space-between; - padding: var(--gap-mid); - color: var(--clr-txt); + gap: var(--uc-padding); + padding: var(--uc-padding); + color: var(--uc-foreground); font-weight: 500; font-size: 1em; - line-height: var(--ui-size); -} - -lr-activity-header lr-icon { - height: var(--ui-size); } lr-activity-header > * { display: flex; align-items: center; } - -lr-activity-header button { - display: inline-flex; - align-items: center; - justify-content: center; - color: var(--clr-txt-mid); -} - -lr-activity-header button:hover { - background-color: var(--clr-background); -} - -lr-activity-header button:active { - background-color: var(--clr-background-dark); -} diff --git a/blocks/CameraSource/camera-source.css b/blocks/CameraSource/camera-source.css index 15353cd75..c2ad41e75 100644 --- a/blocks/CameraSource/camera-source.css +++ b/blocks/CameraSource/camera-source.css @@ -6,12 +6,12 @@ lr-camera-source { height: 100%; max-height: 100%; overflow: hidden; - background-color: var(--clr-background-light); - border-radius: var(--border-radius-element); + background-color: var(--uc-background); + border-radius: var(--uc-radius); } -lr-modal lr-camera-source { - width: min(calc(var(--modal-max-w) - var(--gap-mid) * 2), calc(100vw - var(--gap-mid) * 2)); +[lr-modal] lr-camera-source { + width: min(calc(var(--uc-dialog-max-width) - var(--uc-padding) * 2), calc(100vw - var(--uc-padding) * 2)); height: 100vh; max-height: var(--modal-max-content-height); } @@ -22,7 +22,7 @@ lr-camera-source.initialized { @media only screen and (max-width: 430px) { lr-camera-source { - width: calc(100vw - var(--gap-mid) * 2); + width: calc(100vw - var(--uc-padding) * 2); height: var(--modal-content-height-fill, 100%); } } @@ -33,8 +33,8 @@ lr-camera-source video { max-height: 100%; object-fit: contain; object-position: center center; - background-color: var(--clr-background-dark); - border-radius: var(--border-radius-element); + background-color: var(--uc-muted); + border-radius: var(--uc-radius); } lr-camera-source .toolbar { @@ -43,8 +43,8 @@ lr-camera-source .toolbar { display: flex; justify-content: space-between; width: 100%; - padding: var(--gap-mid); - background-color: var(--clr-background-light); + padding: var(--uc-padding); + background-color: var(--uc-background); } lr-camera-source .content { @@ -52,38 +52,39 @@ lr-camera-source .content { flex: 1; justify-content: center; width: 100%; - padding: var(--gap-mid); + padding: var(--uc-padding); padding-top: 0; overflow: hidden; } lr-camera-source .message-box { - --padding: calc(var(--gap-max) * 2); - display: flex; flex-direction: column; - grid-gap: var(--gap-max); + grid-gap: 40px; align-items: center; justify-content: center; - padding: var(--padding) var(--padding) 0 var(--padding); - color: var(--clr-txt); + padding: 40px 40px 0; + color: var(--uc-foreground); } lr-camera-source .message-box button { - color: var(--clr-btn-txt-primary); - background-color: var(--clr-btn-bgr-primary); + color: var(--uc-primary-foreground); + background-color: var(--uc-primary); } lr-camera-source .shot-btn { position: absolute; - bottom: var(--gap-max); - width: calc(var(--ui-size) * 1.8); - height: calc(var(--ui-size) * 1.8); - color: var(--clr-background-light); - background-color: var(--clr-txt); + bottom: 20px; + width: 58px; + height: 58px; + color: var(--uc-background); + background-color: var(--uc-foreground); border-radius: 50%; opacity: 0.85; - transition: var(--transition-duration) ease; + transition: + bottom var(--uc-transition), + opacity var(--uc-transition), + transform var(--uc-transition); } lr-camera-source .shot-btn:hover { @@ -92,15 +93,15 @@ lr-camera-source .shot-btn:hover { } lr-camera-source .shot-btn:active { - background-color: var(--clr-txt-mid); + transform: scale(1); opacity: 1; } lr-camera-source .shot-btn[disabled] { - bottom: calc(var(--gap-max) * -1 - var(--gap-mid) - var(--ui-size) * 2); + bottom: -80px; } lr-camera-source .shot-btn lr-icon svg { - width: calc(var(--ui-size) / 1.5); - height: calc(var(--ui-size) / 1.5); + width: 20px; + height: 20px; } diff --git a/blocks/CloudImageEditor/src/CloudImageEditorBlock.js b/blocks/CloudImageEditor/src/CloudImageEditorBlock.js index 46c340647..f9d93127a 100644 --- a/blocks/CloudImageEditor/src/CloudImageEditorBlock.js +++ b/blocks/CloudImageEditor/src/CloudImageEditorBlock.js @@ -19,7 +19,7 @@ import { TabId } from './toolbar-constants.js'; export class CloudImageEditorBlock extends Block { ctxOwner = true; - static className = 'cloud-image-editor'; + static styleAttrs = ['lr-cloud-image-editor']; constructor() { super(); diff --git a/blocks/CloudImageEditor/src/CropFrame.js b/blocks/CloudImageEditor/src/CropFrame.js index d001184c7..8b1f79842 100644 --- a/blocks/CloudImageEditor/src/CropFrame.js +++ b/blocks/CloudImageEditor/src/CropFrame.js @@ -49,7 +49,7 @@ export class CropFrame extends Block { * @param {import('./types.js').Direction} direction */ _shouldThumbBeDisabled(direction) { - const imageBox = this.$['*imageBox']; + let imageBox = this.$['*imageBox']; if (!imageBox) { return; } @@ -58,30 +58,30 @@ export class CropFrame extends Block { return true; } - const tooHigh = imageBox.height <= MIN_CROP_SIZE && (direction.includes('n') || direction.includes('s')); - const tooWide = imageBox.width <= MIN_CROP_SIZE && (direction.includes('e') || direction.includes('w')); + let tooHigh = imageBox.height <= MIN_CROP_SIZE && (direction.includes('n') || direction.includes('s')); + let tooWide = imageBox.width <= MIN_CROP_SIZE && (direction.includes('e') || direction.includes('w')); return tooHigh || tooWide; } /** @private */ _createBackdrop() { /** @type {import('./types.js').Rectangle} */ - const cropBox = this.$['*cropBox']; + let cropBox = this.$['*cropBox']; if (!cropBox) { return; } - const { x, y, width, height } = cropBox; - const svg = this.ref['svg-el']; + let { x, y, width, height } = cropBox; + let svg = this.ref['svg-el']; - const mask = createSvgNode('mask', { id: 'backdrop-mask' }); - const maskRectOuter = createSvgNode('rect', { + let mask = createSvgNode('mask', { id: 'backdrop-mask' }); + let maskRectOuter = createSvgNode('rect', { x: 0, y: 0, width: '100%', height: '100%', fill: 'white', }); - const maskRectInner = createSvgNode('rect', { + let maskRectInner = createSvgNode('rect', { x, y, width, @@ -91,7 +91,7 @@ export class CropFrame extends Block { mask.appendChild(maskRectOuter); mask.appendChild(maskRectInner); - const backdropRect = createSvgNode('rect', { + let backdropRect = createSvgNode('rect', { x: 0, y: 0, width: '100%', @@ -126,11 +126,11 @@ export class CropFrame extends Block { /** @private */ _updateBackdrop() { /** @type {import('./types.js').Rectangle} */ - const cropBox = this.$['*cropBox']; + let cropBox = this.$['*cropBox']; if (!cropBox) { return; } - const { x, y, width, height } = cropBox; + let { x, y, width, height } = cropBox; this._backdropMaskInner && setSvgNodeAttrs(this._backdropMaskInner, { x, y, width, height }); } @@ -138,16 +138,16 @@ export class CropFrame extends Block { /** @private */ _updateFrame() { /** @type {import('./types.js').Rectangle} */ - const cropBox = this.$['*cropBox']; + let cropBox = this.$['*cropBox']; if (!cropBox || !this._frameGuides || !this._frameThumbs) { return; } - for (const thumb of Object.values(this._frameThumbs)) { - const { direction, pathNode, interactionNode, groupNode } = thumb; - const isCenter = direction === ''; - const isCorner = direction.length === 2; - const { x, y, width, height } = cropBox; + for (let thumb of Object.values(this._frameThumbs)) { + let { direction, pathNode, interactionNode, groupNode } = thumb; + let isCenter = direction === ''; + let isCorner = direction.length === 2; + let { x, y, width, height } = cropBox; if (isCenter) { const moveThumbRect = { @@ -164,7 +164,7 @@ export class CropFrame extends Block { 1, ); - const { d, center } = isCorner + let { d, center } = isCorner ? cornerPath(cropBox, direction, thumbSizeMultiplier) : sidePath( cropBox, @@ -184,7 +184,7 @@ export class CropFrame extends Block { setSvgNodeAttrs(pathNode, { d }); } - const disableThumb = this._shouldThumbBeDisabled(direction); + let disableThumb = this._shouldThumbBeDisabled(direction); groupNode.setAttribute( 'class', classNames('thumb', { @@ -218,14 +218,14 @@ export class CropFrame extends Block { for (let i = 0; i < 3; i++) { for (let j = 0; j < 3; j++) { - const direction = /** @type {import('./types.js').Direction} */ (`${['n', '', 's'][i]}${['w', '', 'e'][j]}`); - const groupNode = createSvgNode('g'); + let direction = /** @type {import('./types.js').Direction} */ (`${['n', '', 's'][i]}${['w', '', 'e'][j]}`); + let groupNode = createSvgNode('g'); groupNode.classList.add('thumb'); groupNode.setAttribute('with-effects', ''); - const interactionNode = createSvgNode('rect', { + let interactionNode = createSvgNode('rect', { fill: 'transparent', }); - const pathNode = createSvgNode('path', { + let pathNode = createSvgNode('path', { stroke: 'currentColor', fill: 'none', 'stroke-width': THUMB_STROKE_WIDTH, @@ -248,27 +248,27 @@ export class CropFrame extends Block { /** @private */ _createGuides() { - const svg = createSvgNode('svg'); + let svg = createSvgNode('svg'); - const rect = createSvgNode('rect', { + let rect = createSvgNode('rect', { x: 0, y: 0, width: '100%', height: '100%', fill: 'none', - stroke: '#000000', + stroke: 'currentColor', 'stroke-width': GUIDE_STROKE_WIDTH, 'stroke-opacity': 0.5, }); svg.appendChild(rect); for (let i = 1; i <= 2; i++) { - const line = createSvgNode('line', { + let line = createSvgNode('line', { x1: `${GUIDE_THIRD * i}%`, - y1: '0%', + y1: `0%`, x2: `${GUIDE_THIRD * i}%`, - y2: '100%', - stroke: '#000000', + y2: `100%`, + stroke: 'currentColor', 'stroke-width': GUIDE_STROKE_WIDTH, 'stroke-opacity': 0.3, }); @@ -276,12 +276,12 @@ export class CropFrame extends Block { } for (let i = 1; i <= 2; i++) { - const line = createSvgNode('line', { - x1: '0%', + let line = createSvgNode('line', { + x1: `0%`, y1: `${GUIDE_THIRD * i}%`, - x2: '100%', + x2: `100%`, y2: `${GUIDE_THIRD * i}%`, - stroke: '#000000', + stroke: 'currentColor', 'stroke-width': GUIDE_STROKE_WIDTH, 'stroke-opacity': 0.3, }); @@ -295,14 +295,14 @@ export class CropFrame extends Block { /** @private */ _createFrame() { - const svg = this.ref['svg-el']; - const fr = document.createDocumentFragment(); + let svg = this.ref['svg-el']; + let fr = document.createDocumentFragment(); - const frameGuides = this._createGuides(); + let frameGuides = this._createGuides(); fr.appendChild(frameGuides); - const frameThumbs = this._createThumbs(); - for (const { groupNode } of Object.values(frameThumbs)) { + let frameThumbs = this._createThumbs(); + for (let { groupNode } of Object.values(frameThumbs)) { fr.appendChild(groupNode); } @@ -318,15 +318,15 @@ export class CropFrame extends Block { */ _handlePointerDown(direction, e) { if (!this._frameThumbs) return; - const thumb = this._frameThumbs[direction]; + let thumb = this._frameThumbs[direction]; if (this._shouldThumbBeDisabled(direction)) { return; } - const cropBox = this.$['*cropBox']; - const { x: svgX, y: svgY } = this.ref['svg-el'].getBoundingClientRect(); - const x = e.x - svgX; - const y = e.y - svgY; + let cropBox = this.$['*cropBox']; + let { x: svgX, y: svgY } = this.ref['svg-el'].getBoundingClientRect(); + let x = e.x - svgX; + let y = e.y - svgY; this.$.dragging = true; this._draggingThumb = thumb; @@ -362,13 +362,13 @@ export class CropFrame extends Block { e.stopPropagation(); e.preventDefault(); - const svg = this.ref['svg-el']; - const { x: svgX, y: svgY } = svg.getBoundingClientRect(); - const x = e.x - svgX; - const y = e.y - svgY; - const dx = x - this._dragStartPoint[0]; - const dy = y - this._dragStartPoint[1]; - const { direction } = this._draggingThumb; + let svg = this.ref['svg-el']; + let { x: svgX, y: svgY } = svg.getBoundingClientRect(); + let x = e.x - svgX; + let y = e.y - svgY; + let dx = x - this._dragStartPoint[0]; + let dy = y - this._dragStartPoint[1]; + let { direction } = this._draggingThumb; const movedCropBox = this._calcCropBox(direction, [dx, dy]); if (movedCropBox) { @@ -384,7 +384,7 @@ export class CropFrame extends Block { _calcCropBox(direction, delta) { const [dx, dy] = delta; /** @type {import('./types.js').Rectangle} */ - const imageBox = this.$['*imageBox']; + let imageBox = this.$['*imageBox']; let rect = /** @type {import('./types.js').Rectangle} */ (this._dragStartCrop) ?? this.$['*cropBox']; /** @type {import('./types.js').CropPresetList[0]} */ const cropPreset = this.$['*cropPresetList']?.[0]; @@ -412,19 +412,19 @@ export class CropFrame extends Block { _handleSvgPointerMove_(e) { if (!this._frameThumbs) return; - const hoverThumb = Object.values(this._frameThumbs).find((thumb) => { + let hoverThumb = Object.values(this._frameThumbs).find((thumb) => { if (this._shouldThumbBeDisabled(thumb.direction)) { return false; } - const node = thumb.interactionNode; - const bounds = node.getBoundingClientRect(); - const rect = { + let node = thumb.interactionNode; + let bounds = node.getBoundingClientRect(); + let rect = { x: bounds.x, y: bounds.y, width: bounds.width, height: bounds.height, }; - const hover = rectContainsPoint(rect, [e.x, e.y]); + let hover = rectContainsPoint(rect, [e.x, e.y]); return hover; }); @@ -434,7 +434,7 @@ export class CropFrame extends Block { /** @private */ _updateCursor() { - const hoverThumb = this._hoverThumb; + let hoverThumb = this._hoverThumb; this.ref['svg-el'].style.cursor = hoverThumb ? thumbCursor(hoverThumb.direction) : 'initial'; } @@ -447,17 +447,17 @@ export class CropFrame extends Block { /** @param {boolean} visible */ toggleThumbs(visible) { if (!this._frameThumbs) return; - - for (const thumb of Object.values(this._frameThumbs)) { - const { groupNode } = thumb; - groupNode.setAttribute( - 'class', - classNames('thumb', { - 'thumb--hidden': !visible, - 'thumb--visible': visible, - }), - ); - } + Object.values(this._frameThumbs) + .map(({ groupNode }) => groupNode) + .forEach((groupNode) => { + groupNode.setAttribute( + 'class', + classNames('thumb', { + 'thumb--hidden': !visible, + 'thumb--visible': visible, + }), + ); + }); } initCallback() { diff --git a/blocks/CloudImageEditor/src/EditorButtonControl.js b/blocks/CloudImageEditor/src/EditorButtonControl.js index 287b2fa25..9571dc29d 100644 --- a/blocks/CloudImageEditor/src/EditorButtonControl.js +++ b/blocks/CloudImageEditor/src/EditorButtonControl.js @@ -16,11 +16,6 @@ export class EditorButtonControl extends Block { this._titleEl = this.ref['title-el']; this._iconEl = this.ref['icon-el']; - this.setAttribute('role', 'button'); - if (this.tabIndex === -1) { - this.tabIndex = 0; - } - this.sub('title', (title) => { const titleEl = this._titleEl; if (titleEl) { @@ -42,7 +37,8 @@ export class EditorButtonControl extends Block { } EditorButtonControl.template = /* HTML */ ` - - - {{title}} + + + {{title}} + `; diff --git a/blocks/CloudImageEditor/src/EditorFilterControl.js b/blocks/CloudImageEditor/src/EditorFilterControl.js index a15a88784..4ec49e3f0 100644 --- a/blocks/CloudImageEditor/src/EditorFilterControl.js +++ b/blocks/CloudImageEditor/src/EditorFilterControl.js @@ -148,7 +148,8 @@ export class EditorFilterControl extends EditorButtonControl { } EditorFilterControl.template = /* HTML */ ` - - - + + + + `; diff --git a/blocks/CloudImageEditor/src/EditorScroller.js b/blocks/CloudImageEditor/src/EditorScroller.js index d4bccaff2..ccdb9f6c2 100644 --- a/blocks/CloudImageEditor/src/EditorScroller.js +++ b/blocks/CloudImageEditor/src/EditorScroller.js @@ -6,16 +6,28 @@ export class EditorScroller extends Block { initCallback() { super.initCallback(); - this.addEventListener('wheel', (e) => { - e.preventDefault(); - const { deltaY, deltaX } = e; - if (Math.abs(deltaX) > X_THRESHOLD) { - this.scrollLeft += deltaX; - } else { - this.scrollLeft += deltaY; - } + this.addEventListener( + 'wheel', + (e) => { + e.preventDefault(); + + let { deltaY, deltaX } = e; + if (Math.abs(deltaX) > X_THRESHOLD) { + this.scrollLeft += deltaX; + } else { + this.scrollLeft += deltaY; + } + }, + { + passive: false, + }, + ); + + // This fixes some strange bug on MacOS - wheel event doesn't fire for physical mouse wheel if no scroll event attached also + this.addEventListener('scroll', () => {}, { + passive: true, }); } } -EditorScroller.template = /* HTML */ ' '; +EditorScroller.template = /* HTML */ ` `; diff --git a/blocks/CloudImageEditor/src/EditorToolbar.js b/blocks/CloudImageEditor/src/EditorToolbar.js index 7297c04c3..587ec51f1 100644 --- a/blocks/CloudImageEditor/src/EditorToolbar.js +++ b/blocks/CloudImageEditor/src/EditorToolbar.js @@ -21,12 +21,11 @@ function renderTabToggle(id) { return /* HTML */ ` @@ -36,10 +35,14 @@ function renderTabToggle(id) { /** @param {String} id */ function renderTabContent(id) { return /* HTML */ ` - + - + @@ -115,6 +118,10 @@ export class EditorToolbar extends Block { this._activateTab(id, { fromViewer: false }); } }, + tab_role: 'tab', + [`tab_${TabId.TUNING}`]: `tab_${TabId.TUNING}`, + [`tab_${TabId.CROP}`]: `tab_${TabId.CROP}`, + [`tab_${TabId.FILTERS}`]: `tab_${TabId.FILTERS}`, }; /** @private */ @@ -387,15 +394,19 @@ EditorToolbar.template = /* HTML */ ` - + ${ALL_TABS.map(renderTabContent).join('')} - ${ALL_TABS.map(renderTabToggle).join('')} - + + @@ -403,7 +414,7 @@ EditorToolbar.template = /* HTML */ ` - + diff --git a/blocks/CloudImageEditor/src/css/common.css b/blocks/CloudImageEditor/src/css/common.css index 09b4060d9..67d0e0ca6 100644 --- a/blocks/CloudImageEditor/src/css/common.css +++ b/blocks/CloudImageEditor/src/css/common.css @@ -1,67 +1,39 @@ /* TODO: we shuoud use basic theme there */ -:host(.lr-cloud-image-editor), -.lr-cloud-image-editor { - /* Theme settings >>> */ - --rgb-primary-accent: 6, 2, 196; - --rgb-text-base: 0, 0, 0; - --rgb-text-accent-contrast: 255, 255, 255; - --rgb-fill-contrast: 255, 255, 255; - --rgb-fill-shaded: 245, 245, 245; - --rgb-shadow: 0, 0, 0; - --rgb-error: 209, 81, 81; - --opacity-shade-mid: 0.2; - - /* <<< Theme settings */ - - --color-primary-accent: rgb(var(--rgb-primary-accent)); - --color-text-base: rgb(var(--rgb-text-base)); - --color-text-accent-contrast: rgb(var(--rgb-text-accent-contrast)); - --color-text-soft: rgb(var(--rgb-fill-contrast)); - --color-text-error: rgb(var(--rgb-error)); - --color-fill-contrast: rgb(var(--rgb-fill-contrast)); - --color-modal-backdrop: rgba(var(--rgb-fill-shaded), 0.95); - --color-image-background: rgba(var(--rgb-fill-shaded)); - --color-outline: rgba(var(--rgb-text-base), var(--opacity-shade-mid)); - --color-underline: rgba(var(--rgb-text-base), 0.08); - --color-shade: rgba(var(--rgb-text-base), 0.02); +[lr-cloud-image-editor] { + --color-primary-accent: var(--uc-primary); + --color-text-base: var(--uc-foreground); + --color-text-accent-contrast: var(--uc-background); + --color-fill-contrast: var(--uc-background); + --color-modal-backdrop: oklch(0 0 0 / 0.1); + --color-image-background: var(--uc-muted); --color-focus-ring: var(--color-primary-accent); - --color-input-placeholder: rgba(var(--rgb-text-base), 0.32); - --color-error: rgb(var(--rgb-error)); + --color-crop-guides: var(--uc-foreground); - --font-size-ui: 16px; - --font-size-title: 18px; - --font-weight-title: 500; - --font-size-soft: 14px; + --font-size-ui: var(--uc-font-size); - --size-touch-area: 40px; - --size-panel-heading: 66px; + --size-touch-area: var(--uc-button-size); + --size-panel-heading: calc(var(--uc-button-size) + var(--uc-padding) * 2); --size-ui-min-width: 130px; --size-line-width: 1px; --size-modal-width: 650px; + --size-icon: calc(var(--uc-button-size) / 2); /* TODO: remove icon size overrides */ - --border-radius-connect: 2px; - --border-radius-editor: 3px; - --border-radius-thumb: 4px; - --border-radius-ui: 5px; - --border-radius-base: 6px; + --border-radius-editor: var(--uc-radius); + --border-radius-thumb: var(--uc-radius); + --border-radius-ui: var(--uc-radius); + --border-radius-base: var(--uc-radius); --cldtr-gap-min: 5px; --cldtr-gap-mid-1: 10px; --cldtr-gap-mid-2: 15px; --cldtr-gap-max: 20px; - --opacity-min: var(--opacity-shade-mid); - --opacity-mid: 0.1; - --opacity-max: 0.05; - --transition-duration-2: var(--transition-duration-all, 0.2s); --transition-duration-3: var(--transition-duration-all, 0.3s); --transition-duration-4: var(--transition-duration-all, 0.4s); --transition-duration-5: var(--transition-duration-all, 0.5s); - --shadow-base: 0px 5px 15px rgba(var(--rgb-shadow), 0.1), 0px 1px 4px rgba(var(--rgb-shadow), 0.15); - --modal-header-opacity: 1; --modal-header-height: var(--size-panel-heading); --modal-toolbar-height: var(--size-panel-heading); @@ -74,61 +46,54 @@ max-height: 100%; } -:host(.lr-cloud-image-editor) :is([can-handle-paste]:hover, [can-handle-paste]:focus), -.lr-cloud-image-editor :is([can-handle-paste]:hover, [can-handle-paste]:focus) { +[lr-cloud-image-editor] :is([can-handle-paste]:hover, [can-handle-paste]:focus) { --can-handle-paste: 'true'; } -:host(.lr-cloud-image-editor) - :is([tabindex][focus-visible], [tabindex]:hover, [with-effects][focus-visible], [with-effects]:hover), -.lr-cloud-image-editor +[lr-cloud-image-editor] :is([tabindex][focus-visible], [tabindex]:hover, [with-effects][focus-visible], [with-effects]:hover) { --filter-effect: var(--hover-filter) !important; --opacity-effect: var(--hover-opacity) !important; --color-effect: var(--hover-color-rgb) !important; + --background-effect: var(--hover-background) !important; } -:host(.lr-cloud-image-editor) :is([tabindex]:active, [with-effects]:active), -.lr-cloud-image-editor :is([tabindex]:active, [with-effects]:active) { +[lr-cloud-image-editor] :is([tabindex]:active, [with-effects]:active) { --filter-effect: var(--down-filter) !important; --opacity-effect: var(--down-opacity) !important; --color-effect: var(--down-color-rgb) !important; + --background-effect: var(--down-background) !important; } -:host(.lr-cloud-image-editor) :is([tabindex][active], [with-effects][active]), -.lr-cloud-image-editor :is([tabindex][active], [with-effects][active]) { +[lr-cloud-image-editor] :is([tabindex][active], [with-effects][active]) { --filter-effect: var(--active-filter) !important; --opacity-effect: var(--active-opacity) !important; --color-effect: var(--active-color-rgb) !important; + --background-effect: var(--active-background) !important; } -:host(.lr-cloud-image-editor) [hidden-scrollbar]::-webkit-scrollbar, -.lr-cloud-image-editor [hidden-scrollbar]::-webkit-scrollbar { +[lr-cloud-image-editor] [hidden-scrollbar]::-webkit-scrollbar { display: none; } -:host(.lr-cloud-image-editor) [hidden-scrollbar], -.lr-cloud-image-editor [hidden-scrollbar] { +[lr-cloud-image-editor] [hidden-scrollbar] { -ms-overflow-style: none; scrollbar-width: none; } -:host(.lr-cloud-image-editor.editor_ON), -.lr-cloud-image-editor.editor_ON { +[lr-cloud-image-editor].editor_ON { --modal-header-opacity: 0; --modal-header-height: 0px; --modal-toolbar-height: calc(var(--size-panel-heading) * 2); } -:host(.lr-cloud-image-editor.editor_OFF), -.lr-cloud-image-editor.editor_OFF { +[lr-cloud-image-editor].editor_OFF { --modal-header-opacity: 1; --modal-header-height: var(--size-panel-heading); --modal-toolbar-height: var(--size-panel-heading); } -:host(.lr-cloud-image-editor) > .wrapper, -.lr-cloud-image-editor > .wrapper { +[lr-cloud-image-editor] > .wrapper { --l-min-img-height: var(--modal-toolbar-height); --l-max-img-height: 100%; --l-edit-button-width: 120px; @@ -143,23 +108,20 @@ } @media only screen and (max-width: 800px) { - :host(.lr-cloud-image-editor) > .wrapper, - .lr-cloud-image-editor > .wrapper { + [lr-cloud-image-editor] > .wrapper { --l-edit-button-width: 70px; --l-toolbar-horizontal-padding: var(--cldtr-gap-min); } } -:host(.lr-cloud-image-editor) > .wrapper > .viewport, -.lr-cloud-image-editor > .wrapper > .viewport { +[lr-cloud-image-editor] > .wrapper > .viewport { display: flex; align-items: center; justify-content: center; overflow: hidden; } -:host(.lr-cloud-image-editor) > .wrapper > .viewport > .image_container > .image, -.lr-cloud-image-editor > .wrapper > .viewport > .image_container > .image { +[lr-cloud-image-editor] > .wrapper > .viewport > .image_container > .image { --viewer-image-opacity: 1; position: absolute; @@ -178,15 +140,13 @@ pointer-events: auto; } -:host(.lr-cloud-image-editor) > .wrapper > .viewport > .image_container > .image.image_visible_viewer, -.lr-cloud-image-editor > .wrapper > .viewport > .image_container > .image.image_visible_viewer { +[lr-cloud-image-editor] > .wrapper > .viewport > .image_container > .image.image_visible_viewer { transition: opacity var(--transition-duration-3) ease-in-out, transform var(--transition-duration-4); } -:host(.lr-cloud-image-editor) > .wrapper > .viewport > .image_container > .image.image_hidden_to_cropper, -.lr-cloud-image-editor > .wrapper > .viewport > .image_container > .image.image_hidden_to_cropper { +[lr-cloud-image-editor] > .wrapper > .viewport > .image_container > .image.image_hidden_to_cropper { --viewer-image-opacity: 0; background-image: var(--transparent-pixel); @@ -197,8 +157,7 @@ pointer-events: none; } -:host(.lr-cloud-image-editor) > .wrapper > .viewport > .image_container > .image.image_hidden_effects, -.lr-cloud-image-editor > .wrapper > .viewport > .image_container > .image.image_hidden_effects { +[lr-cloud-image-editor] > .wrapper > .viewport > .image_container > .image.image_hidden_effects { --viewer-image-opacity: 0; transform: scale(1); @@ -208,8 +167,7 @@ pointer-events: none; } -:host(.lr-cloud-image-editor) > .wrapper > .viewport > .image_container, -.lr-cloud-image-editor > .wrapper > .viewport > .image_container { +[lr-cloud-image-editor] > .wrapper > .viewport > .image_container { position: relative; display: block; width: 100%; @@ -218,14 +176,12 @@ transition: var(--transition-duration-3); } -:host(.lr-cloud-image-editor) > .wrapper > .toolbar, -.lr-cloud-image-editor > .wrapper > .toolbar { +[lr-cloud-image-editor] > .wrapper > .toolbar { position: relative; transition: 0.3s; } -:host(.lr-cloud-image-editor) > .wrapper > .toolbar > .toolbar_content, -.lr-cloud-image-editor > .wrapper > .toolbar > .toolbar_content { +[lr-cloud-image-editor] > .wrapper > .toolbar > .toolbar_content { position: absolute; bottom: 0px; left: 0px; @@ -236,8 +192,7 @@ background-color: var(--color-fill-contrast); } -:host(.lr-cloud-image-editor) > .wrapper > .toolbar > .toolbar_content.toolbar_content__viewer, -.lr-cloud-image-editor > .wrapper > .toolbar > .toolbar_content.toolbar_content__viewer { +[lr-cloud-image-editor] > .wrapper > .toolbar > .toolbar_content.toolbar_content__viewer { display: flex; align-items: center; justify-content: space-between; @@ -246,19 +201,16 @@ padding-left: var(--l-toolbar-horizontal-padding); } -:host(.lr-cloud-image-editor) > .wrapper > .toolbar > .toolbar_content.toolbar_content__editor, -.lr-cloud-image-editor > .wrapper > .toolbar > .toolbar_content.toolbar_content__editor { +[lr-cloud-image-editor] > .wrapper > .toolbar > .toolbar_content.toolbar_content__editor { display: flex; } -:host(.lr-cloud-image-editor) > .wrapper > .viewport > .info_pan, -.lr-cloud-image-editor > .wrapper > .viewport > .info_pan { +[lr-cloud-image-editor] > .wrapper > .viewport > .info_pan { position: absolute; user-select: none; } -:host(.lr-cloud-image-editor) > .wrapper > .viewport > .file_type_outer, -.lr-cloud-image-editor > .wrapper > .viewport > .file_type_outer { +[lr-cloud-image-editor] > .wrapper > .viewport > .file_type_outer { position: absolute; z-index: 2; display: flex; @@ -267,13 +219,11 @@ user-select: none; } -:host(.lr-cloud-image-editor) > .wrapper > .viewport > .file_type_outer > .file_type, -.lr-cloud-image-editor > .wrapper > .viewport > .file_type_outer > .file_type { +[lr-cloud-image-editor] > .wrapper > .viewport > .file_type_outer > .file_type { padding: 4px 0.8em; } -:host(.lr-cloud-image-editor) > .wrapper > .network_problems_splash, -.lr-cloud-image-editor > .wrapper > .network_problems_splash { +[lr-cloud-image-editor] > .wrapper > .network_problems_splash { position: absolute; z-index: 4; display: flex; @@ -283,8 +233,7 @@ background-color: var(--color-fill-contrast); } -:host(.lr-cloud-image-editor) > .wrapper > .network_problems_splash > .network_problems_content, -.lr-cloud-image-editor > .wrapper > .network_problems_splash > .network_problems_content { +[lr-cloud-image-editor] > .wrapper > .network_problems_splash > .network_problems_content { display: flex; flex: 1; flex-direction: column; @@ -292,34 +241,24 @@ justify-content: center; } -:host(.lr-cloud-image-editor) - > .wrapper - > .network_problems_splash - > .network_problems_content - > .network_problems_icon, -.lr-cloud-image-editor > .wrapper > .network_problems_splash > .network_problems_content > .network_problems_icon { +[lr-cloud-image-editor] > .wrapper > .network_problems_splash > .network_problems_content > .network_problems_icon { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; - color: rgba(var(--rgb-text-base), 0.6); - background-color: rgba(var(--rgb-fill-shaded)); + color: var(--uc-foreground); + background-color: var(--uc-muted); border-radius: 50%; } -:host(.lr-cloud-image-editor) - > .wrapper - > .network_problems_splash - > .network_problems_content - > .network_problems_text, -.lr-cloud-image-editor > .wrapper > .network_problems_splash > .network_problems_content > .network_problems_text { +[lr-cloud-image-editor] > .wrapper > .network_problems_splash > .network_problems_content > .network_problems_text { margin-top: var(--cldtr-gap-max); font-size: var(--font-size-ui); + color: var(--uc-foreground); } -:host(.lr-cloud-image-editor) > .wrapper > .network_problems_splash > .network_problems_footer, -.lr-cloud-image-editor > .wrapper > .network_problems_splash > .network_problems_footer { +[lr-cloud-image-editor] > .wrapper > .network_problems_splash > .network_problems_footer { display: flex; align-items: center; justify-content: center; @@ -382,28 +321,40 @@ lr-editor-button-control, lr-editor-crop-button-control, lr-editor-filter-control, lr-editor-operation-control { - --l-base-min-width: 40px; - --l-base-height: var(--l-base-min-width); + --l-base-min-width: var(--uc-button-size); + --l-base-height: var(--uc-button-size); --opacity-effect: var(--idle-opacity); --color-effect: var(--idle-color-rgb); + --background-effect: var(--idle-background); --filter-effect: var(--idle-filter); - --idle-color-rgb: var(--rgb-text-base); - --idle-opacity: 0.05; + + --idle-color-rgb: var(--uc-secondary-foreground); + --idle-opacity: 1; --idle-filter: 1; - --hover-color-rgb: var(--idle-color-rgb); - --hover-opacity: 0.08; + --idle-background: var(--uc-secondary); + --hover-color-rgb: var(--uc-secondary-foreground); + --hover-opacity: 1; --hover-filter: 0.8; + --hover-background: var(--uc-secondary-hover); --down-color-rgb: var(--hover-color-rgb); - --down-opacity: 0.12; + --down-opacity: 1; --down-filter: 0.6; + --down-background: var(--uc-secondary); +} +lr-editor-button-control > button, +lr-editor-crop-button-control > button, +lr-editor-filter-control > button, +lr-editor-operation-control > button { + all: unset; position: relative; display: grid; grid-template-columns: var(--l-base-min-width) auto; grid-template-rows: 100%; align-items: center; height: var(--l-base-height); - color: rgba(var(--idle-color-rgb)); + color: var(--color-effect); + opacity: var(--opacity-effect); outline: none; cursor: pointer; transition: var(--l-width-transition); @@ -412,8 +363,8 @@ lr-editor-operation-control { :where(lr-editor-button-control, lr-editor-crop-button-control, lr-editor-filter-control, lr-editor-operation-control) > lr-icon > svg { - width: 20px; - height: 20px; + width: var(--size-icon); + height: var(--size-icon); } lr-editor-filter-control > lr-icon.original-icon > svg { @@ -425,7 +376,12 @@ lr-editor-button-control.active, lr-editor-operation-control.active, lr-editor-crop-button-control.active, lr-editor-filter-control.active { - --idle-color-rgb: var(--rgb-primary-accent); + --idle-color-rgb: var(--uc-primary); + --idle-background: var(--uc-primary-transparent); + --idle-opacity: 0.9; + --hover-color-rgb: var(--uc-primary); + --hover-background: var(--uc-primary-transparent); + --hover-opacity: 1; } lr-editor-filter-control.not_active .preview[loaded] { @@ -440,39 +396,40 @@ lr-editor-button-control.not_active, lr-editor-operation-control.not_active, lr-editor-crop-button-control.not_active, lr-editor-filter-control.not_active { - --idle-color-rgb: var(--rgb-text-base); + --idle-color-rgb: var(--uc-secondary-foreground); } -lr-editor-button-control > .before, -lr-editor-operation-control > .before, -lr-editor-crop-button-control > .before, -lr-editor-filter-control > .before { +lr-editor-button-control > button::before, +lr-editor-operation-control > button::before, +lr-editor-crop-button-control > button::before, +lr-editor-filter-control > button::before { position: absolute; - right: 0px; - left: 0px; + content: ''; + right: 0; + left: 0; z-index: -1; width: 100%; height: 100%; - background-color: rgba(var(--color-effect), var(--opacity-effect)); + background-color: var(--background-effect); border-radius: var(--border-radius-editor); transition: var(--transition-duration-3); } -lr-editor-button-control > .title, -lr-editor-operation-control > .title, -lr-editor-crop-button-control > .title, -lr-editor-filter-control > .title { +lr-editor-button-control > button .title, +lr-editor-operation-control > button .title, +lr-editor-crop-button-control > button .title, +lr-editor-filter-control > button .title { padding-right: var(--cldtr-gap-mid-1); font-size: 0.7em; letter-spacing: 1.004px; text-transform: uppercase; } -lr-editor-filter-control > .preview { +lr-editor-filter-control > button .preview { position: absolute; - right: 0px; - left: 0px; - z-index: 1; + right: 0; + left: 0; + z-index: -1; width: 100%; height: var(--l-base-height); background-repeat: no-repeat; @@ -484,7 +441,7 @@ lr-editor-filter-control > .preview { } lr-editor-filter-control > .original-icon { - color: var(--color-text-base); + color: var(--color-effect); opacity: 0.3; } @@ -499,6 +456,7 @@ lr-editor-image-cropper { opacity: 0; pointer-events: none; touch-action: none; + color: var(--color-crop-guides); } lr-editor-image-cropper.active_from_editor { @@ -611,7 +569,7 @@ lr-editor-slider { align-items: center; justify-content: center; width: 100%; - height: 66px; + height: var(--size-panel-heading); } lr-editor-toolbar { @@ -623,16 +581,16 @@ lr-editor-toolbar { @media only screen and (max-width: 600px) { lr-editor-toolbar { --l-tab-gap: var(--cldtr-gap-mid-1); - --l-slider-padding: var(--cldtr-gap-min); - --l-controls-padding: var(--cldtr-gap-min); + --l-slider-padding: var(--uc-padding); + --l-controls-padding: var(--uc-padding); } } @media only screen and (min-width: 601px) { lr-editor-toolbar { - --l-tab-gap: calc(var(--cldtr-gap-mid-1) + var(--cldtr-gap-max)); - --l-slider-padding: var(--cldtr-gap-mid-1); - --l-controls-padding: var(--cldtr-gap-mid-1); + --l-tab-gap: var(--cldtr-gap-max); + --l-slider-padding: var(--uc-padding); + --l-controls-padding: var(--uc-padding); } } @@ -697,7 +655,7 @@ lr-editor-toolbar > .toolbar-container > .sub-toolbar > .controls-row > .tab-tog left: 0px; width: var(--size-touch-area); height: 2px; - background-color: var(--color-primary-accent); + background-color: var(--uc-secondary-foreground); transform: translateX(0px); transition: transform var(--transition-duration-3); } @@ -741,7 +699,7 @@ lr-editor-toolbar > .toolbar-container > .sub-toolbar > .controls-row > .tab-tog } lr-editor-toolbar > .toolbar-container > .sub-toolbar > .controls-row > .tab-toggles > .tab-toggle > lr-btn-ui { - width: 40px; + width: var(--uc-button-size); } lr-editor-toolbar @@ -753,8 +711,8 @@ lr-editor-toolbar > lr-btn-ui > lr-icon > svg { - width: 100%; - height: 100%; + width: var(--size-icon); + height: var(--size-icon); } lr-editor-toolbar > .toolbar-container > .sub-toolbar > .tab-content-row > .tab-content .controls-list_align { @@ -763,14 +721,14 @@ lr-editor-toolbar > .toolbar-container > .sub-toolbar > .tab-content-row > .tab- grid-template-columns: 1fr auto 1fr; box-sizing: border-box; min-width: 100%; - padding-left: var(--cldtr-gap-max); + padding-left: var(--uc-padding); } lr-editor-toolbar > .toolbar-container > .sub-toolbar > .tab-content-row > .tab-content .controls-list_inner { display: grid; grid-area: inner; grid-auto-flow: column; - grid-gap: calc((var(--cldtr-gap-min) - 1px) * 3); + gap: 6px; } lr-editor-toolbar @@ -779,7 +737,7 @@ lr-editor-toolbar > .tab-content-row > .tab-content .controls-list_inner:last-child { - padding-right: var(--cldtr-gap-max); + padding-right: var(--uc-padding); } lr-editor-toolbar .controls-list_last-item { @@ -807,10 +765,7 @@ lr-editor-toolbar .info-tooltip_wrapper { lr-editor-toolbar .info-tooltip { z-index: 3; - padding-top: calc(var(--cldtr-gap-min) / 2); - padding-right: var(--cldtr-gap-min); - padding-bottom: calc(var(--cldtr-gap-min) / 2); - padding-left: var(--cldtr-gap-min); + padding: 3px 6px; color: var(--color-text-base); font-size: 0.7em; letter-spacing: 1px; @@ -832,19 +787,30 @@ lr-editor-toolbar .slider { padding-left: var(--l-slider-padding); } -lr-btn-ui { +lr-btn-ui > button { --filter-effect: var(--idle-brightness); --opacity-effect: var(--idle-opacity); --color-effect: var(--idle-color-rgb); - --l-transition-effect: var(--css-transition, color var(--transition-duration-2), filter var(--transition-duration-2)); - + --background-effect: var(--idle-background); + --l-transition-effect: var( + --css-transition, + color var(--transition-duration-2), + background-color var(--transition-duration-2), + filter var(--transition-duration-2) + ); + + all: unset; display: inline-flex; align-items: center; box-sizing: var(--css-box-sizing, border-box); - height: var(--css-height, var(--size-touch-area)); - padding-right: var(--css-padding-right, var(--cldtr-gap-mid-1)); - padding-left: var(--css-padding-left, var(--cldtr-gap-mid-1)); - color: rgba(var(--color-effect), var(--opacity-effect)); + height: var(--css-height, var(--uc-button-size)); + padding-right: var(--css-padding-right, 14px); + padding-left: var(--css-padding-left, 14px); + font-size: 1em; + color: var(--color-effect); + background-color: var(--background-effect); + border-radius: var(--uc-radius); + opacity: var(--opacity-effect); outline: none; cursor: pointer; filter: brightness(var(--filter-effect)); @@ -860,7 +826,7 @@ lr-btn-ui .icon { display: flex; align-items: center; justify-content: center; - color: rgba(var(--color-effect), var(--opacity-effect)); + color: var(--color-effect); filter: brightness(var(--filter-effect)); transition: var(--l-transition-effect); } @@ -885,49 +851,127 @@ lr-btn-ui .icon_hidden { margin: 0; } -lr-btn-ui.primary { - --idle-color-rgb: var(--rgb-primary-accent); +lr-btn-ui.primary > button { + --idle-color-rgb: var(--uc-primary-foreground); --idle-brightness: 1; - --idle-opacity: 0.6; - --hover-color-rgb: var(--idle-color-rgb); + --idle-opacity: 1; + --idle-background: var(--uc-primary); + --hover-color-rgb: var(--uc-primary-foreground); --hover-brightness: 1; --hover-opacity: 1; - --down-color-rgb: var(--hover-color-rgb); + --hover-background: var(--uc-primary-hover); + --down-color-rgb: var(--uc-primary-foreground); --down-brightness: 0.75; --down-opacity: 1; - --active-color-rgb: var(--rgb-primary-accent); + --down-background: var(--uc-primary); + --active-color-rgb: var(--uc-primary-foreground); --active-brightness: 1; --active-opacity: 1; + --active-background: var(--uc-primary); } -lr-btn-ui.boring { - --idle-color-rgb: var(--rgb-text-base); +lr-btn-ui.primary-icon > button { + --idle-color-rgb: var(--uc-primary); --idle-brightness: 1; - --idle-opacity: 0.6; - --hover-color-rgb: var(--rgb-text-base); + --idle-opacity: 1; + --idle-background: transparent; + --hover-color-rgb: var(--uc-primary); --hover-brightness: 1; --hover-opacity: 1; - --down-color-rgb: var(--hover-color-rgb); + --hover-background: var(--uc-primary-transparent); + --down-color-rgb: var(--uc-primary); + --down-brightness: 0.75; + --down-opacity: 1; + --down-background: var(--uc-primary-transparent); + --active-color-rgb: var(--uc-primary-foreground); + --active-brightness: 1; + --active-opacity: 1; + --active-background: var(--uc-primary); + + padding: 0; + width: var(--uc-button-size); +} + +lr-btn-ui.secondary > button { + --idle-color-rgb: var(--uc-secondary-foreground); + --idle-brightness: 1; + --idle-opacity: 1; + --idle-background: var(--uc-secondary); + --hover-color-rgb: var(--uc-secondary-foreground); + --hover-brightness: 1; + --hover-opacity: 1; + --hover-background: var(--uc-secondary-hover); + --down-color-rgb: var(--uc-secondary-foreground); --down-brightness: 1; --down-opacity: 1; - --active-color-rgb: var(--rgb-primary-accent); + --down-background: var(--uc-secondary-hover); + --active-color-rgb: var(--uc-secondary-foreground); --active-brightness: 1; --active-opacity: 1; + --active-background: transparent; } -lr-btn-ui.default { - --idle-color-rgb: var(--rgb-text-base); +lr-btn-ui.secondary-icon > button { + --idle-color-rgb: var(--uc-secondary-foreground); --idle-brightness: 1; - --idle-opacity: 0.6; - --hover-color-rgb: var(--rgb-primary-accent); + --idle-opacity: 1; + --idle-background: transparent; + --hover-color-rgb: var(--uc-secondary-foreground); --hover-brightness: 1; --hover-opacity: 1; - --down-color-rgb: var(--hover-color-rgb); + --hover-background: var(--uc-secondary); + --down-color-rgb: var(--uc-secondary-foreground); + --down-brightness: 1; + --down-opacity: 1; + --down-background: var(--uc-secondary); + --active-color-rgb: var(--uc-secondary-foreground); + --active-brightness: 1; + --active-opacity: 1; + --active-background: transparent; + + padding: 0; + width: var(--uc-button-size); +} + +lr-btn-ui.tab > button { + --idle-color-rgb: var(--uc-secondary-foreground); + --idle-brightness: 1; + --idle-opacity: 1; + --idle-background: transparent; + --hover-color-rgb: var(--uc-secondary-foreground); + --hover-brightness: 1; + --hover-opacity: 1; + --hover-background: var(--uc-secondary); + --down-color-rgb: var(--uc-secondary-foreground); + --down-brightness: 1; + --down-opacity: 1; + --down-background: var(--uc-secondary); + --active-color-rgb: var(--uc-secondary-foreground); + --active-brightness: 1; + --active-opacity: 1; + --active-background: transparent; + + padding: 0; + width: var(--uc-button-size); +} + +lr-btn-ui.default > button { + --idle-color-rgb: var(--uc-secondary-foreground); + --idle-brightness: 1; + --idle-opacity: 1; + --idle-background: var(--uc-secondary); + --hover-color-rgb: var(--uc-secondary-foreground); + --hover-brightness: 1; + --hover-opacity: 1; + --hover-background: var(--uc-secondary-hover); + --down-color-rgb: var(--uc-secondary-foreground); --down-brightness: 0.75; --down-opacity: 1; - --active-color-rgb: var(--rgb-primary-accent); + --down-background: var(--uc-secondary); + --active-color-rgb: var(--uc-primary); --active-brightness: 1; --active-opacity: 1; + --active-background: var(--uc-primary-transparent); } lr-line-loader-ui { @@ -949,7 +993,7 @@ lr-line-loader-ui .inner { lr-line-loader-ui .line { width: 100%; height: 100%; - background-color: var(--color-primary-accent); + background-color: var(--uc-primary); transform: translateX(-101%); transition: transform 1s; } @@ -958,11 +1002,11 @@ lr-slider-ui { --l-thumb-size: 24px; --l-zero-dot-size: 5px; --l-zero-dot-offset: 2px; - --idle-color-rgb: var(--rgb-text-base); - --hover-color-rgb: var(--rgb-primary-accent); - --down-color-rgb: var(--rgb-primary-accent); + --idle-color-rgb: var(--uc-foreground); + --hover-color-rgb: var(--uc-primary); + --down-color-rgb: var(--uc-primary); --color-effect: var(--idle-color-rgb); - --l-color: rgb(var(--color-effect)); + --l-color: var(--color-effect); position: relative; display: flex; @@ -981,7 +1025,9 @@ lr-slider-ui .thumb { border-radius: 50%; transform: translateX(0px); opacity: 1; - transition: opacity var(--transition-duration-2); + transition: + opacity var(--transition-duration-2), + background-color var(--transition-duration-2); } lr-slider-ui .steps { @@ -1001,7 +1047,7 @@ lr-slider-ui .border-step { height: 10px; border-right: 1px solid var(--l-color); opacity: 0.6; - transition: var(--transition-duration-2); + transition: border-color var(--transition-duration-2); } lr-slider-ui .minor-step { @@ -1009,7 +1055,7 @@ lr-slider-ui .minor-step { height: 4px; border-right: 1px solid var(--l-color); opacity: 0.2; - transition: var(--transition-duration-2); + transition: border-color var(--transition-duration-2); } lr-slider-ui .zero-dot { @@ -1049,19 +1095,12 @@ lr-presence-toggle.hidden { pointer-events: none; } -/* TODO: remove ctx-provider */ -/* stylelint-disable-next-line plugin/stylelint-force-app-name-prefix */ -ctx-provider { - --color-text-base: black; - --color-primary-accent: blue; +lr-presence-toggle.initial { + display: none !important; + transition: none !important; +} - display: flex; - align-items: center; - justify-content: center; - width: 190px; - height: 40px; - padding-right: 10px; - padding-left: 10px; - background-color: #f5f5f5; - border-radius: 3px; +[lr-cloud-image-editor] [role='button']:focus-visible, +[lr-cloud-image-editor] button:focus-visible { + outline: 1px auto -webkit-focus-ring-color; } diff --git a/blocks/CloudImageEditor/src/css/icons.css b/blocks/CloudImageEditor/src/css/icons.css index bedf8eb19..7fa07e5fa 100644 --- a/blocks/CloudImageEditor/src/css/icons.css +++ b/blocks/CloudImageEditor/src/css/icons.css @@ -1,7 +1,12 @@ -.lr-cloud-image-editor lr-icon { +:where([lr-cloud-image-editor]) lr-icon { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; } + +:where([lr-cloud-image-editor]) lr-icon svg { + width: calc(var(--uc-button-size) / 2); + height: calc(var(--uc-button-size) / 2); +} diff --git a/blocks/CloudImageEditor/src/elements/button/LrBtnUi.js b/blocks/CloudImageEditor/src/elements/button/LrBtnUi.js index 993954036..971036316 100644 --- a/blocks/CloudImageEditor/src/elements/button/LrBtnUi.js +++ b/blocks/CloudImageEditor/src/elements/button/LrBtnUi.js @@ -15,6 +15,8 @@ export class LrBtnUi extends Block { icon: '', iconCss: this._iconCss(), theme: null, + 'aria-role': '', + 'aria-controls': '', }; this.defineAccessor('active', (active) => { @@ -54,13 +56,17 @@ export class LrBtnUi extends Block { this._iconSingle = false; }); - this.setAttribute('role', 'button'); - if (this.tabIndex === -1) { - this.tabIndex = 0; - } if (!this.hasAttribute('theme')) { this.setAttribute('theme', 'default'); } + + this.defineAccessor('aria-role', (value) => { + this.$['aria-role'] = value || ''; + }); + + this.defineAccessor('aria-controls', (value) => { + this.$['aria-controls'] = value || ''; + }); } set reverse(val) { @@ -73,9 +79,12 @@ export class LrBtnUi extends Block { } } } + LrBtnUi.bindAttributes({ text: 'text', icon: 'icon', reverse: 'reverse', theme: 'theme' }); LrBtnUi.template = /* HTML */ ` - - {{text}} + + + {{text}} + `; diff --git a/blocks/CloudImageEditor/src/elements/presence-toggle/PresenceToggle.js b/blocks/CloudImageEditor/src/elements/presence-toggle/PresenceToggle.js index c516afc0a..575aabe53 100644 --- a/blocks/CloudImageEditor/src/elements/presence-toggle/PresenceToggle.js +++ b/blocks/CloudImageEditor/src/elements/presence-toggle/PresenceToggle.js @@ -1,5 +1,5 @@ -import { Block } from '../../../../../abstract/Block.js'; import { applyClassNames } from '../../lib/classNames.js'; +import { Block } from '../../../../../abstract/Block.js'; /** * @typedef {Object} Style @@ -55,14 +55,17 @@ export class PresenceToggle extends Block { initCallback() { super.initCallback(); - this.setAttribute('hidden', ''); + + this.classList.toggle('initial', true); if (!this._externalTransitions) { this.classList.add(DEFAULT_STYLE.transition); } this._handleVisible(); - setTimeout(() => this.removeAttribute('hidden'), 0); + setTimeout(() => { + this.classList.toggle('initial', false); + }, 0); } } -PresenceToggle.template = /* HTML */ ' '; +PresenceToggle.template = /* HTML */ ` `; diff --git a/blocks/CloudImageEditor/src/elements/slider/SliderUi.js b/blocks/CloudImageEditor/src/elements/slider/SliderUi.js index 0cd02cfb8..86944a639 100644 --- a/blocks/CloudImageEditor/src/elements/slider/SliderUi.js +++ b/blocks/CloudImageEditor/src/elements/slider/SliderUi.js @@ -173,7 +173,6 @@ SliderUi.template = /* HTML */ ` class="input" type="range" ref="input-el" - tabindex="0" set="oninput: on.sliderInput; onchange: on.sliderChange; @min: min; @max: max; @value: defaultValue;" /> `; diff --git a/blocks/CloudImageEditor/src/icons/closeMax.svg b/blocks/CloudImageEditor/src/icons/closeMax.svg index 3e621f4de..88e57184c 100644 --- a/blocks/CloudImageEditor/src/icons/closeMax.svg +++ b/blocks/CloudImageEditor/src/icons/closeMax.svg @@ -1,3 +1,3 @@ - - + + diff --git a/blocks/CloudImageEditor/src/icons/done.svg b/blocks/CloudImageEditor/src/icons/done.svg index 87a628a61..78ff9b54e 100644 --- a/blocks/CloudImageEditor/src/icons/done.svg +++ b/blocks/CloudImageEditor/src/icons/done.svg @@ -1,3 +1,3 @@ - - + + diff --git a/blocks/CloudImageEditor/src/icons/edit-file.svg b/blocks/CloudImageEditor/src/icons/edit-file.svg new file mode 100644 index 000000000..c88b71952 --- /dev/null +++ b/blocks/CloudImageEditor/src/icons/edit-file.svg @@ -0,0 +1,3 @@ + + + diff --git a/blocks/CloudImageEditor/src/icons/original.svg b/blocks/CloudImageEditor/src/icons/original.svg index abe71893a..906db13f9 100644 --- a/blocks/CloudImageEditor/src/icons/original.svg +++ b/blocks/CloudImageEditor/src/icons/original.svg @@ -1,3 +1,3 @@ - + diff --git a/blocks/CloudImageEditor/src/svg-sprite.js b/blocks/CloudImageEditor/src/svg-sprite.js index 89542dbfc..ac2f498be 100644 --- a/blocks/CloudImageEditor/src/svg-sprite.js +++ b/blocks/CloudImageEditor/src/svg-sprite.js @@ -1 +1 @@ -export default ""; +export default ""; \ No newline at end of file diff --git a/blocks/CloudImageEditorActivity/index.css b/blocks/CloudImageEditorActivity/index.css index 58dd3fb84..8ad271e8d 100644 --- a/blocks/CloudImageEditorActivity/index.css +++ b/blocks/CloudImageEditorActivity/index.css @@ -4,10 +4,10 @@ lr-cloud-image-editor-activity { width: 100%; height: 100%; overflow: hidden; - background-color: var(--clr-background-light); + background-color: var(--uc-background); } -lr-modal lr-cloud-image-editor-activity { - width: min(calc(var(--modal-max-w) - var(--gap-mid) * 2), calc(100vw - var(--gap-mid) * 2)); +[lr-modal] lr-cloud-image-editor-activity { + width: min(calc(var(--uc-dialog-max-width) - var(--uc-padding) * 2), calc(100vw - var(--uc-padding) * 2)); height: var(--modal-content-height-fill, 100%); } diff --git a/blocks/Color/Color.js b/blocks/Color/Color.js deleted file mode 100644 index 6410f84f3..000000000 --- a/blocks/Color/Color.js +++ /dev/null @@ -1,17 +0,0 @@ -import { Block } from '../../abstract/Block.js'; - -export class Color extends Block { - init$ = { - ...this.init$, - inputOpacity: 0, - '*selectedColor': '#f00', - onChange: () => { - this.$['*selectedColor'] = this.ref.input.value; - }, - }; -} - -Color.template = /* HTML */ ` - - -`; diff --git a/blocks/Color/color.css b/blocks/Color/color.css deleted file mode 100644 index a79312818..000000000 --- a/blocks/Color/color.css +++ /dev/null @@ -1,32 +0,0 @@ -lr-color { - position: relative; - display: inline-flex; - align-items: center; - justify-content: center; - width: var(--ui-size); - height: var(--ui-size); - overflow: hidden; - background-color: var(--clr-background); - cursor: pointer; -} - -lr-color[current] { - background-color: var(--clr-txt); -} - -lr-color input[type='color'] { - position: absolute; - display: block; - width: 100%; - height: 100%; - opacity: 0; -} - -lr-color .current-color { - position: absolute; - width: 50%; - height: 50%; - border: 2px solid #fff; - border-radius: 100%; - pointer-events: none; -} diff --git a/blocks/ConfirmationDialog/ConfirmationDialog.js b/blocks/ConfirmationDialog/ConfirmationDialog.js deleted file mode 100644 index 626fb32da..000000000 --- a/blocks/ConfirmationDialog/ConfirmationDialog.js +++ /dev/null @@ -1,77 +0,0 @@ -import { ActivityBlock } from '../../abstract/ActivityBlock.js'; - -export class UiConfirmation { - captionL10nStr = 'confirm-your-action'; - messageL10Str = 'are-you-sure'; - confirmL10nStr = 'yes'; - denyL10nStr = 'no'; - confirmAction() { - console.log('Confirmed'); - } - denyAction() { - this.historyBack(); - } -} - -export class ConfirmationDialog extends ActivityBlock { - activityType = ActivityBlock.activities.CONFIRMATION; - - /** @private */ - _defaults = new UiConfirmation(); - - init$ = { - ...this.init$, - activityCaption: '', - messageTxt: '', - confirmBtnTxt: '', - denyBtnTxt: '', - '*confirmation': null, - onConfirm: this._defaults.confirmAction, - onDeny: this._defaults.denyAction.bind(this), - }; - - initCallback() { - super.initCallback(); - this.set$({ - messageTxt: this.l10n(this._defaults.messageL10Str), - confirmBtnTxt: this.l10n(this._defaults.confirmL10nStr), - denyBtnTxt: this.l10n(this._defaults.denyL10nStr), - }); - this.sub('*confirmation', (/** @type {UiConfirmation} */ cfn) => { - if (!cfn) { - return; - } - this.set$({ - '*currentActivity': ActivityBlock.activities.CONFIRMATION, - activityCaption: this.l10n(cfn.captionL10nStr), - messageTxt: this.l10n(cfn.messageL10Str), - confirmBtnTxt: this.l10n(cfn.confirmL10nStr), - denyBtnTxt: this.l10n(cfn.denyL10nStr), - onDeny: () => { - cfn.denyAction(); - }, - onConfirm: () => { - cfn.confirmAction(); - }, - }); - }); - } -} - -ConfirmationDialog.template = /* HTML */ ` - - - - - {{activityCaption}} - - - - - - {{messageTxt}} - - {{denyBtnTxt}} - {{confirmBtnTxt}} - -`; diff --git a/blocks/ConfirmationDialog/confirmation.css b/blocks/ConfirmationDialog/confirmation.css deleted file mode 100644 index f84b3a22d..000000000 --- a/blocks/ConfirmationDialog/confirmation.css +++ /dev/null @@ -1,21 +0,0 @@ -lr-confirmation-dialog { - display: block; - padding: var(--gap-mid); - padding-top: var(--gap-max); -} - -lr-confirmation-dialog .message { - display: flex; - justify-content: center; - padding: var(--gap-mid); - padding-bottom: var(--gap-max); - font-weight: 500; - font-size: 1.1em; -} - -lr-confirmation-dialog .toolbar { - display: grid; - grid-template-columns: 1fr 1fr; - gap: var(--gap-mid); - margin-top: var(--gap-mid); -} diff --git a/blocks/Copyright/copyright.css b/blocks/Copyright/copyright.css index 919645431..713c10171 100644 --- a/blocks/Copyright/copyright.css +++ b/blocks/Copyright/copyright.css @@ -1,17 +1,31 @@ lr-copyright { display: flex; - align-items: flex-end; + width: 100%; + justify-content: center; } lr-copyright .credits { - padding: 0 var(--gap-mid) var(--gap-mid) calc(var(--gap-mid) * 1.5); - color: var(--clr-txt-lightest); + all: unset; + position: absolute; + bottom: 12px; + background-color: var(--uc-background); + padding: 2px 5px; + border-radius: 6px; + color: var(--uc-muted-foreground); font-weight: normal; - font-size: 0.85em; - opacity: 0.7; - transition: var(--transition-duration) ease; + font-size: 12px; + opacity: 0.9; + cursor: pointer; + transition: + opacity var(--uc-transition), + background-color var(--uc-transition); +} + +lr-copyright .credits:focus-visible { + outline: 1px auto -webkit-focus-ring-color; } lr-copyright .credits:hover { opacity: 1; + background-color: var(--uc-muted); } diff --git a/blocks/DropArea/DropArea.js b/blocks/DropArea/DropArea.js index 4c5197168..371632aac 100644 --- a/blocks/DropArea/DropArea.js +++ b/blocks/DropArea/DropArea.js @@ -12,6 +12,7 @@ const GLOBAL_CTX_NAME = 'lr-drop-area'; const REGISTRY_KEY = `${GLOBAL_CTX_NAME}/registry`; export class DropArea extends UploaderBlock { + static styleAttrs = [...super.styleAttrs, 'lr-drop-area']; constructor() { super(); @@ -164,10 +165,22 @@ export class DropArea extends UploaderBlock { }); if (this.$.isClickable) { - // @private - this._onAreaClicked = () => { - this.openSystemDialog(); + /** + * @private + * @param {KeyboardEvent | Event} event + */ + this._onAreaClicked = (event) => { + if (event.type === 'keydown') { + // @ts-ignore + if (event.code === 'Space' || event.code === 'Enter') { + this.openSystemDialog(); + } + } else if (event.type === 'click') { + this.openSystemDialog(); + } }; + + this.addEventListener('keydown', this._onAreaClicked); this.addEventListener('click', this._onAreaClicked); } } @@ -227,6 +240,7 @@ export class DropArea extends UploaderBlock { this._destroyDropzone?.(); this._destroyContentWrapperDropzone?.(); if (this._onAreaClicked) { + this.removeEventListener('keydown', this._onAreaClicked); this.removeEventListener('click', this._onAreaClicked); } } diff --git a/blocks/DropArea/drop-area.css b/blocks/DropArea/drop-area.css index 636fa1239..2e44584be 100644 --- a/blocks/DropArea/drop-area.css +++ b/blocks/DropArea/drop-area.css @@ -1,13 +1,15 @@ -lr-drop-area { - padding: var(--gap-min); +:where([lr-drop-area]) { + padding: 2px; overflow: hidden; - border: var(--border-dashed); - border-radius: var(--border-radius-frame); - transition: var(--transition-duration) ease; + border: 1px dashed var(--uc-border); + border-radius: calc(var(--uc-radius) * 1.75); + transition: + border var(--uc-transition), + border-radius var(--uc-transition); } -lr-drop-area, -lr-drop-area .content-wrapper { +:where([lr-drop-area]), +:where([lr-drop-area]) .content-wrapper { display: flex; align-items: center; justify-content: center; @@ -15,122 +17,127 @@ lr-drop-area .content-wrapper { height: 100%; } -lr-drop-area .text { +:where([lr-drop-area]) .text { position: relative; - margin: var(--gap-mid); - color: var(--clr-txt-light); - transition: var(--transition-duration) ease; + margin: var(--uc-padding); + color: var(--uc-muted-foreground); + transition: color var(--uc-transition); } -lr-drop-area[ghost][drag-state='inactive'] { +:where([lr-drop-area])[ghost][drag-state='inactive'] { display: none; - opacity: 0; } -lr-drop-area[ghost]:not([fullscreen]):is([drag-state='active'], [drag-state='near'], [drag-state='over']) { - background: var(--clr-background); +:where([lr-drop-area])[ghost]:not([fullscreen]):is([drag-state='active'], [drag-state='near'], [drag-state='over']) { + background: var(--uc-background); } -lr-drop-area[with-icon] +:where([lr-drop-area])[with-icon] > .content-wrapper:is([drag-state='active'], [drag-state='near'], [drag-state='over']) :is(.text, .icon-container) { - color: var(--clr-accent); + color: var(--uc-primary); } -lr-drop-area:is([drag-state='active'], [drag-state='near'], [drag-state='over'], :hover) { - color: var(--clr-accent); - background: var(--clr-accent-lightest); - border-color: var(--clr-accent-light); +:where([lr-drop-area]):is([drag-state='active'], [drag-state='near'], [drag-state='over'], :hover) { + color: var(--uc-primary); + background: var(--uc-primary-transparent); + border-color: var(--uc-primary-transparent); } -lr-drop-area:is([drag-state='active'], [drag-state='near']) { +:where([lr-drop-area]):is([drag-state='active'], [drag-state='near']) { opacity: 1; } -lr-drop-area[drag-state='over'] { - border-color: var(--clr-accent); +:where([lr-drop-area])[drag-state='over'] { + border-color: var(--uc-primary); opacity: 1; } -lr-drop-area[with-icon] { - min-height: calc(var(--ui-size) * 6); +:where([lr-drop-area])[with-icon] { + min-height: 180px; } -lr-drop-area[with-icon] .content-wrapper { +:where([lr-drop-area])[with-icon] .content-wrapper { display: flex; flex-direction: column; } -lr-drop-area[with-icon] .text { - color: var(--clr-txt); +:where([lr-drop-area])[with-icon] .text { + color: var(--uc-foreground); font-weight: 500; font-size: 1.1em; } -lr-drop-area[with-icon] .icon-container { +:where([lr-drop-area])[with-icon] .icon-container { position: relative; - width: calc(var(--ui-size) * 2); - height: calc(var(--ui-size) * 2); - margin: var(--gap-mid); + width: 64px; + height: 64px; + margin: var(--uc-padding); overflow: hidden; - color: var(--clr-txt); - background-color: var(--clr-background); + color: var(--uc-foreground); + background-color: var(--uc-muted); border-radius: 50%; - transition: var(--transition-duration) ease; + transition: + color var(--uc-transition), + background-color var(--uc-transition); } -lr-drop-area[with-icon] lr-icon { +:where([lr-drop-area])[with-icon] lr-icon { position: absolute; - top: calc(50% - var(--ui-size) / 2); - left: calc(50% - var(--ui-size) / 2); - transition: var(--transition-duration) ease; + width: 32px; + height: 32px; + top: calc(50% - 16px); + left: calc(50% - 16px); + transition: transform var(--uc-transition); } -lr-drop-area[with-icon] lr-icon:last-child { - transform: translateY(calc(var(--ui-size) * 1.5)); +:where([lr-drop-area])[with-icon] lr-icon:last-child { + transform: translateY(48px); } -lr-drop-area[with-icon]:hover .icon-container, -lr-drop-area[with-icon]:hover .text { - color: var(--clr-accent); +:where([lr-drop-area])[with-icon]:hover .icon-container, +:where([lr-drop-area])[with-icon]:hover .text { + color: var(--uc-primary); } -lr-drop-area[with-icon]:hover .icon-container { - background-color: var(--clr-accent-lightest); +:where([lr-drop-area])[with-icon]:hover .icon-container { + background-color: var(--uc-primary-transparent); } -lr-drop-area[with-icon] +:where([lr-drop-area])[with-icon] > .content-wrapper:is([drag-state='active'], [drag-state='near'], [drag-state='over']) .icon-container { - color: white; - background-color: var(--clr-accent); + color: var(--uc-primary-foreground); + background-color: var(--uc-primary); } -lr-drop-area[with-icon] > .content-wrapper:is([drag-state='active'], [drag-state='near'], [drag-state='over']) .text { - color: var(--clr-accent); +:where([lr-drop-area])[with-icon] + > .content-wrapper:is([drag-state='active'], [drag-state='near'], [drag-state='over']) + .text { + color: var(--uc-primary); } -lr-drop-area[with-icon] +:where([lr-drop-area])[with-icon] > .content-wrapper:is([drag-state='active'], [drag-state='near'], [drag-state='over']) lr-icon:first-child { - transform: translateY(calc(var(--ui-size) * -1.5)); + transform: translateY(-48px); } -lr-drop-area[with-icon] +:where([lr-drop-area])[with-icon] > .content-wrapper:is([drag-state='active'], [drag-state='near'], [drag-state='over']) lr-icon:last-child { transform: translateY(0); } -lr-drop-area[with-icon] > .content-wrapper[drag-state='near'] lr-icon:last-child { +:where([lr-drop-area])[with-icon] > .content-wrapper[drag-state='near'] lr-icon:last-child { transform: scale(1.3); } -lr-drop-area[with-icon] > .content-wrapper[drag-state='over'] lr-icon:last-child { +:where([lr-drop-area])[with-icon] > .content-wrapper[drag-state='over'] lr-icon:last-child { transform: scale(1.5); } -lr-drop-area[fullscreen] { +:where([lr-drop-area])[fullscreen] { position: fixed; top: 0; right: 0; @@ -140,37 +147,42 @@ lr-drop-area[fullscreen] { display: flex; align-items: center; justify-content: center; - width: calc(100vw - var(--gap-mid) * 2); - height: calc(100vh - var(--gap-mid) * 2); - margin: var(--gap-mid); + width: calc(100vw - var(--uc-padding) * 2); + height: calc(100vh - var(--uc-padding) * 2); + margin: var(--uc-padding); } -lr-drop-area[fullscreen] .content-wrapper { +:where([lr-drop-area])[fullscreen] .content-wrapper { width: 100%; - max-width: calc(var(--modal-normal-w) * 0.8); - height: calc(var(--ui-size) * 6); - color: var(--clr-txt); - background-color: var(--clr-background-light); - border-radius: var(--border-radius-frame); - box-shadow: var(--modal-shadow); - transition: var(--transition-duration) ease; -} - -lr-drop-area[with-icon][fullscreen][drag-state='active'] > .content-wrapper, -lr-drop-area[with-icon][fullscreen][drag-state='near'] > .content-wrapper { - transform: translateY(var(--gap-mid)); + max-width: calc(var(--uc-dialog-width) * 0.8); + height: 180px; + color: var(--uc-foreground); + background-color: var(--uc-background); + border-radius: calc(var(--uc-radius) * 1.75); + box-shadow: var(--uc-dialog-shadow); + transition: + color var(--uc-transition), + background-color var(--uc-transition), + box-shadow var(--uc-transition), + border-radius var(--uc-transition), + transform var(--uc-transition); +} + +:where([lr-drop-area])[with-icon][fullscreen][drag-state='active'] > .content-wrapper, +:where([lr-drop-area])[with-icon][fullscreen][drag-state='near'] > .content-wrapper { + transform: translateY(10px); opacity: 0; } -lr-drop-area[with-icon][fullscreen][drag-state='over'] > .content-wrapper { +:where([lr-drop-area])[with-icon][fullscreen][drag-state='over'] > .content-wrapper { transform: translateY(0px); opacity: 1; } -:is(lr-drop-area[with-icon][fullscreen]) > .content-wrapper lr-icon:first-child { - transform: translateY(calc(var(--ui-size) * -1.5)); +:is(:where([lr-drop-area])[with-icon][fullscreen]) > .content-wrapper lr-icon:first-child { + transform: translateY(-48px); } -lr-drop-area[clickable] { +:where([lr-drop-area])[clickable] { cursor: pointer; } diff --git a/blocks/EditableCanvas/CanMan.js b/blocks/EditableCanvas/CanMan.js deleted file mode 100644 index 613c261f4..000000000 --- a/blocks/EditableCanvas/CanMan.js +++ /dev/null @@ -1,210 +0,0 @@ -// Canvas Manipulator -import { applyAttributes, applyStyles } from '@symbiotejs/symbiote'; -const SVGNS = 'http://www.w3.org/2000/svg'; - -export class CanMan { - _syncSvgSize() { - const rect = this.svgGroupEl.getBoundingClientRect(); - applyAttributes(this.svgEl, { - viewBox: `0, 0, ${rect.width}, ${rect.height}`, - width: rect.width, - height: rect.height, - }); - } - - _syncCanvas() { - return new Promise((resolve, reject) => { - const url = URL.createObjectURL( - new Blob([this.svgEl.outerHTML], { - type: 'image/svg+xml', - }), - ); - this.vImg.onload = () => { - this.can.height = this.vImg.height; - this.can.width = this.vImg.width; - this.ctx.drawImage(this.vImg, 0, 0, this.vImg.width, this.vImg.height); - resolve(); - }; - this.vImg.onerror = () => { - reject(); - }; - this.vImg.src = url; - }); - } - - _backSyncSvg() { - this.svgGroupEl.style.transform = null; - this.svgGroupEl.style.filter = null; - applyAttributes(this.svgEl, { - viewBox: `0, 0, ${this.can.width}, ${this.can.height}`, - width: this.can.width, - height: this.can.height, - }); - applyAttributes(this.svgImgEl, { - href: this.can.toDataURL('image/png'), - width: this.can.width, - height: this.can.height, - }); - for (const obj of this._addedObjects) { - obj.remove(); - } - return new Promise((resolve, reject) => { - this.svgImgEl.onload = () => { - resolve(); - }; - this.svgImgEl.onerror = () => { - reject(); - }; - }); - } - - async _syncAll() { - this._syncSvgSize(); - await this._syncCanvas(); - await this._backSyncSvg(); - } - - /** @param {import('./EditableCanvas.js').RefMap} refMap */ - constructor(refMap) { - /** @type {HTMLCanvasElement} */ - this.can = refMap.canvas; - /** @type {SVGElement} */ - this.svgEl = refMap.svg; - this.svgGroupEl = refMap.svgGroup; - this.svgImgEl = refMap.svgImg; - this.vImg = new Image(); - - this.ctx = refMap.canvCtx; - - this.currentColor = CanMan.defaultColor; - - this._addedObjects = new Set(); - - window.setTimeout(() => { - this._backSyncSvg(); - }, 100); - } - - applyCss(cssMap) { - applyStyles(this.svgGroupEl, cssMap); - } - - getImg() { - const img = new Image(); - img.src = this.can.toDataURL('image/png'); - return new Promise((resolve, reject) => { - img.onload = () => { - resolve(img); - }; - img.onerror = () => { - reject(img); - }; - }); - } - - rotate() { - this.applyCss({ - 'transform-origin': '0 0', - transform: `rotate(90deg) translateY(-${this.can.height}px)`, - }); - this._syncAll(); - } - - /** @param {'vertical' | 'horizontal'} type */ - flip(type) { - this.applyCss({ - 'transform-origin': '50% 50%', - transform: `scale(${type === 'vertical' ? '1, -1' : '-1, 1'})`, - }); - this._syncAll(); - } - - brightness(val) { - this.applyCss({ - filter: `brightness(${val}%)`, - }); - } - - contrast(val) { - this.applyCss({ - filter: `contrast(${val}%)`, - }); - } - - saturate(val) { - this.applyCss({ - filter: `saturate(${val}%)`, - }); - } - - setColor(val) { - this.currentColor = val; - } - - startText() { - const onStart = (e) => { - const text = document.createElementNS(SVGNS, 'text'); - // @ts-ignore - applyAttributes(text, { - fill: this.currentColor, - x: e.offsetX, - y: e.offsetY, - }); - text.textContent = 'TEXT'; - this.svgGroupEl.appendChild(text); - this._addedObjects.add(text); - text.focus(); - this.svgEl.removeEventListener('mousedown', onStart); - }; - this.svgEl.addEventListener('mousedown', onStart); - } - - stopText() { - this.bake(); - } - - startDraw() { - this.svgEl.addEventListener('mousedown', (e) => { - const pLine = document.createElementNS(SVGNS, 'polyline'); - // @ts-ignore - applyAttributes(pLine, { - fill: 'none', - stroke: this.currentColor, - 'stroke-width': '4px', - }); - this.svgGroupEl.appendChild(pLine); - this._addedObjects.add(pLine); - const points = []; - this.svgEl.onmousemove = (e) => { - points.push(`${e.offsetX},${e.offsetY}`); - pLine.setAttribute('points', points.join(' ')); - }; - }); - window.addEventListener('mouseup', () => { - this.svgEl.onmousemove = null; - this.bake(); - }); - window.addEventListener('mouseleave', () => { - this.svgEl.onmousemove = null; - this.bake(); - }); - } - - /** @param {Boolean} val */ - removeMode(val) { - if (val) { - } - } - - resize() {} - - crop() {} - - bake() { - this._syncAll(); - } - - restore() {} -} - -CanMan.defaultColor = '#f00'; diff --git a/blocks/EditableCanvas/EditableCanvas.js b/blocks/EditableCanvas/EditableCanvas.js deleted file mode 100644 index efcf18918..000000000 --- a/blocks/EditableCanvas/EditableCanvas.js +++ /dev/null @@ -1,104 +0,0 @@ -import { applyStyles } from '@symbiotejs/symbiote'; -import { Block } from '../../abstract/Block.js'; -import { checkerboardCssBg } from '../svg-backgrounds/svg-backgrounds.js'; - -/** - * @typedef {Object} RefMap - * @property {import('./EditableCanvas.js').EditableCanvas} parent - * @property {HTMLCanvasElement} canvas - * @property {CanvasRenderingContext2D} canvCtx - * @property {SVGElement} svg - * @property {SVGElement} svgGroup - * @property {SVGImageElement} svgImg - */ - -export class EditableCanvas extends Block { - init$ = { - ...this.init$, - refMap: null, - disabled: true, - toolbarHidden: true, - checkerboard: false, - }; - - constructor() { - super(); - applyStyles(this, { - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - }); - } - - initCallback() { - super.initCallback(); - this.sub('disabled', () => { - this.$.toolbarHidden = this.hasAttribute('disabled') && this.getAttribute('disabled') !== 'false'; - }); - this.sub('checkerboard', () => { - this.style.backgroundImage = this.hasAttribute('checkerboard') ? `url(${checkerboardCssBg()})` : 'unset'; - }); - /** @type {HTMLCanvasElement} */ - // @ts-ignore - this.canvas = this.ref.cvs; - this.canvCtx = this.canvas.getContext('2d'); - this.$.refMap = { - parent: this, - canvas: this.canvas, - canvCtx: this.canvCtx, - svg: this.ref.svg, - svgGroup: this.ref.svg_g, - svgImg: this.ref.svg_img, - }; - } - - /** @param {HTMLImageElement} img */ - setImage(img) { - if (img.height && img.width) { - this.canvas.height = img.height; - this.canvas.width = img.width; - this.canvCtx.drawImage(img, 0, 0, img.width, img.height); - } else { - this.clear(); - img.onload = () => { - this.canvas.height = img.height; - this.canvas.width = img.width; - this.canvCtx.drawImage(img, 0, 0, img.width, img.height); - }; - } - } - - /** @param {File} imgFile */ - setImageFile(imgFile) { - const img = new Image(); - const url = URL.createObjectURL(imgFile); - img.src = url; - this.setImage(img); - } - - /** @param {String} url */ - setImageUrl(url) { - const img = new Image(); - img.src = url; - this.setImage(img); - } - - clear() { - this.canvCtx.clearRect(0, 0, this.canvas.width, this.canvas.height); - } -} - -EditableCanvas.template = /* HTML */ ` - - - - - - - -`; - -EditableCanvas.bindAttributes({ - disabled: 'disabled', - checkerboard: 'checkerboard', -}); diff --git a/blocks/EditableCanvas/EditableCanvasToolbar.js b/blocks/EditableCanvas/EditableCanvasToolbar.js deleted file mode 100644 index 5f8073749..000000000 --- a/blocks/EditableCanvas/EditableCanvasToolbar.js +++ /dev/null @@ -1,144 +0,0 @@ -import { Block } from '../../abstract/Block.js'; -import { Color } from '../Color/Color.js'; -import { Range } from '../Range/Range.js'; -import { CanMan } from './CanMan.js'; - -import { getButtons } from './buttons.js'; - -// TODO: get rid of side effects -Range.reg('range'); -Color.reg('color'); - -const FS_ICON = { - FS: 'fullscreen', - EXIT: 'fullscreen-exit', -}; - -export class EditorToolbar extends Block { - get actionsMap() { - return { - fullscreen: () => { - if (document.fullscreenElement === this.rMap.parent) { - document.exitFullscreen(); - this.$.fsIcon = FS_ICON.FS; - } else { - this.rMap.parent.requestFullscreen(); - this.$.fsIcon = FS_ICON.EXIT; - } - }, - rotate_cw: () => { - this.canMan.rotate(); - }, - flip_v: () => { - this.canMan.flip('vertical'); - }, - flip_h: () => { - this.canMan.flip('horizontal'); - }, - brightness: () => { - this.rangeCtx = 'brightness'; - this.set$({ - rangeActive: true, - }); - this.bindL10n('rangeCaption', () => this.l10n('brightness')); - }, - contrast: () => { - this.rangeCtx = 'contrast'; - this.set$({ - rangeActive: true, - }); - this.bindL10n('rangeCaption', () => this.l10n('contrast')); - }, - saturation: () => { - this.rangeCtx = 'saturate'; - this.set$({ - rangeActive: true, - }); - this.bindL10n('rangeCaption', () => this.l10n('saturation')); - }, - resize: () => { - this.canMan.resize(); - }, - crop: () => { - this.canMan.crop(); - }, - color: () => { - this.ref.color.dispatchEvent(new MouseEvent('click')); - }, - text: () => { - this.canMan.startText(); - }, - draw: () => { - this.canMan.startDraw(); - }, - cancel: () => { - this.canMan.restore(); - }, - }; - } - - init$ = { - ...this.init$, - fsIcon: FS_ICON.FS, - rangeActive: false, - rangeCaption: '', - - onBtnClick: (e) => { - this.canMan.stopText(); - this.rangeCtx = null; - - this.set$({ - rangeActive: false, - rangeCaption: '', - '*rangeValue': 100, - }); - /** @type {HTMLButtonElement} */ - const btnEl = /** @type {Element} */ (e.target).closest('[action]'); - if (btnEl) { - this.buttons.add(btnEl); - - for (const btn of this.buttons) { - if (btn === btnEl) { - btn.setAttribute('current', ''); - } else { - btn.removeAttribute('current', ''); - } - } - } - const action = btnEl.getAttribute('action'); - console.log(action); - if (!action) { - return; - } - this.actionsMap[action](); - }, - onColor: () => false, - }; - - buttons = new Set(); - /** @type {import('./EditableCanvas.js').EditableCanvas} */ - editor = null; - - initCallback() { - super.initCallback(); - this.defineAccessor('refMap', (/** @type {import('./EditableCanvas.js').RefMap} */ rMap) => { - if (!rMap) { - return; - } - this.rMap = rMap; - /** @type {CanMan} */ - this.canMan = new CanMan(rMap); - // console.log(rMap); - }); - this.sub('*rangeValue', (val) => { - this.canMan?.[this.rangeCtx]?.(val); - }); - this.sub('*selectedColor', (val) => { - this.canMan?.setColor(val); - }); - } -} -EditorToolbar.template = /* HTML */ ` - ${getButtons()} - -`; diff --git a/blocks/EditableCanvas/buttons.js b/blocks/EditableCanvas/buttons.js deleted file mode 100644 index 4638323f9..000000000 --- a/blocks/EditableCanvas/buttons.js +++ /dev/null @@ -1,111 +0,0 @@ -export const buttonsModel = [ - { - action: 'fullscreen', - icon: '', - l10n_name: 'toggle-fullscreen', - set: '@name: fsIcon', - }, - // { - // action: 'guides', - // icon: 'edit-guides', - // l10n_name: 'toggle-guides', - // set: '', - // }, - { - action: 'rotate_cw', - icon: 'edit-rotate', - l10n_name: 'rotate', - set: '', - }, - { - action: 'flip_v', - icon: 'edit-flip-v', - l10n_name: 'flip-vertical', - set: '', - }, - { - action: 'flip_h', - icon: 'edit-flip-h', - l10n_name: 'flip-horizontal', - set: '', - }, - { - action: 'brightness', - icon: 'edit-brightness', - l10n_name: 'brightness', - set: '', - }, - { - action: 'contrast', - icon: 'edit-contrast', - l10n_name: 'contrast', - set: '', - }, - { - action: 'saturation', - icon: 'edit-saturation', - l10n_name: 'saturation', - set: '', - }, - // { - // action: 'resize', - // icon: 'edit-resize', - // l10n_name: 'resize', - // set: '', - // }, - // { - // action: 'crop', - // icon: 'edit-crop', - // l10n_name: 'crop', - // set: '', - // }, - { - clr: true, - }, - { - action: 'text', - icon: 'edit-text', - l10n_name: 'text', - set: '', - }, - { - action: 'draw', - icon: 'edit-draw', - l10n_name: 'draw', - set: '', - }, - { - action: 'cancel', - icon: 'close', - l10n_name: 'cancel-edit', - set: '', - }, -]; - -function getBthHtml(btn) { - return /* HTML */ ` - - -`.trim(); -} - -const clrHtml = /* HTML */ ``; - -export function getButtons() { - return buttonsModel.reduce((acc, btn) => { - // biome-ignore lint/suspicious/noAssignInExpressions: It will be removed soon - // biome-ignore lint/style/noParameterAssign: It will be removed soon - return (acc += btn.clr ? clrHtml : getBthHtml(btn)); - }, ''); -} diff --git a/blocks/EditableCanvas/editable-canvas.css b/blocks/EditableCanvas/editable-canvas.css deleted file mode 100644 index 2808e694a..000000000 --- a/blocks/EditableCanvas/editable-canvas.css +++ /dev/null @@ -1,80 +0,0 @@ -lr-editable-canvas { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; -} - -lr-editable-canvas > .img-view { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: 100%; - max-width: 100%; - height: 100%; - max-height: 100%; - object-fit: scale-down; -} - -lr-editable-canvas-toolbar { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 10000; - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - pointer-events: none; -} - -lr-editable-canvas-toolbar .btns { - position: absolute; - left: var(--gap-mid); - display: grid; - pointer-events: all; -} - -lr-editable-canvas-toolbar .btns > button { - display: inline-flex; - width: var(--ui-size); - height: var(--ui-size); - color: var(--clr-txt); - background-color: var(--clr-background); - border-radius: 0; -} - -lr-editable-canvas-toolbar .btns > button:first-of-type { - border-top-left-radius: var(--border-radius-element); - border-top-right-radius: var(--border-radius-element); -} - -lr-editable-canvas-toolbar .btns > button:last-of-type { - border-bottom-right-radius: var(--border-radius-element); - border-bottom-left-radius: var(--border-radius-element); -} - -lr-editable-canvas-toolbar .btns > button[current] { - color: var(--clr-txt); - background-color: var(--clr-background); -} - -lr-editable-canvas-toolbar > lr-range { - position: absolute !important; - bottom: 0; - width: 100%; - transition: 0.2s; - pointer-events: all; -} - -lr-editable-canvas-toolbar > lr-range:not([visible]) { - transform: translateY(60px); -} diff --git a/blocks/EditableCanvas/test/test.htm b/blocks/EditableCanvas/test/test.htm deleted file mode 100644 index 62b40b5ba..000000000 --- a/blocks/EditableCanvas/test/test.htm +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - LocalEditor - - - - - - - - diff --git a/blocks/EditableCanvas/test/test.jpg b/blocks/EditableCanvas/test/test.jpg deleted file mode 100644 index f5b07c5fe..000000000 Binary files a/blocks/EditableCanvas/test/test.jpg and /dev/null differ diff --git a/blocks/ExternalSource/ExternalSource.js b/blocks/ExternalSource/ExternalSource.js index 7d2953137..871e63675 100644 --- a/blocks/ExternalSource/ExternalSource.js +++ b/blocks/ExternalSource/ExternalSource.js @@ -70,7 +70,7 @@ export class ExternalSource extends UploaderBlock { super.initCallback(); this.registerActivity(this.activityType, { onActivate: () => { - const { externalSourceType } = /** @type {ActivityParams} */ (this.activityParams); + let { externalSourceType } = /** @type {ActivityParams} */ (this.activityParams); this.set$({ activityCaption: `${externalSourceType?.[0].toUpperCase()}${externalSourceType?.slice(1)}`, @@ -147,18 +147,23 @@ export class ExternalSource extends UploaderBlock { * @param {string} propName */ getCssValue(propName) { - const style = window.getComputedStyle(this); + let style = window.getComputedStyle(this); return style.getPropertyValue(propName).trim(); } /** @private */ applyStyles() { - const colors = { - backgroundColor: this.getCssValue('--clr-background-light'), - textColor: this.getCssValue('--clr-txt'), - shadeColor: this.getCssValue('--clr-shade-lv1'), - linkColor: '#157cfc', - linkColorHover: '#3891ff', + let colors = { + radius: this.getCssValue('--uc-radius'), + backgroundColor: this.getCssValue('--uc-background'), + textColor: this.getCssValue('--uc-foreground'), + secondaryColor: this.getCssValue('--uc-secondary'), + secondaryForegroundColor: this.getCssValue('--uc-secondary-foreground'), + secondaryHover: this.getCssValue('--uc-secondary-hover'), + linkColor: this.getCssValue('--uc-primary'), + linkColorHover: this.getCssValue('--uc-primary-hover'), + fontFamily: this.getCssValue('--uc-font-family'), + fontSize: this.getCssValue('--uc-font-size'), }; this.sendMessage({ @@ -188,7 +193,7 @@ export class ExternalSource extends UploaderBlock { mountIframe() { /** @type {HTMLIFrameElement} */ // @ts-ignore - const iframe = create({ + let iframe = create({ tag: 'iframe', attributes: { src: this.remoteUrl(), @@ -238,9 +243,12 @@ ExternalSource.template = /* HTML */ ` {{counter}} - - - + `; diff --git a/blocks/ExternalSource/buildStyles.js b/blocks/ExternalSource/buildStyles.js index 3fc43f3f3..388d349f4 100644 --- a/blocks/ExternalSource/buildStyles.js +++ b/blocks/ExternalSource/buildStyles.js @@ -1,23 +1,56 @@ +// @ts-check + +/** + * @param {Record>} style + * @returns + */ const styleToCss = (style) => { const css = Object.keys(style).reduce((acc, selector) => { const propertiesObj = style[selector]; const propertiesStr = Object.keys(propertiesObj).reduce((acc, prop) => { const value = propertiesObj[prop]; - return `${acc}${prop}: ${value};`; + return acc + `${prop}: ${value};`; }, ''); - return `${acc}${selector}{${propertiesStr}}`; + return acc + `${selector}{${propertiesStr}}`; }, ''); return css; }; -export function buildStyles({ textColor, backgroundColor, linkColor, linkColorHover, shadeColor }) { - const border = `solid 1px ${shadeColor}`; +/** + * @param {{ + * textColor: string; + * backgroundColor: string; + * linkColor: string; + * linkColorHover: string; + * secondaryColor: string; + * secondaryHover: string; + * secondaryForegroundColor: string; + * fontFamily: string; + * fontSize: string; + * radius: string; + * }} options + */ +export function buildStyles({ + textColor, + backgroundColor, + linkColor, + linkColorHover, + secondaryColor, + secondaryHover, + secondaryForegroundColor, + fontFamily, + fontSize, + radius, +}) { + const border = `solid 1px ${secondaryColor}`; // TODO: we need to update source source styles, add css custom properties to control theme return styleToCss({ body: { color: textColor, 'background-color': backgroundColor, + 'font-family': fontFamily, + 'font-size': fontSize, }, '.side-bar': { background: 'inherit', @@ -36,7 +69,7 @@ export function buildStyles({ textColor, backgroundColor, linkColor, linkColorHo color: 'inherit', }, '.list-table-row:hover': { - background: shadeColor, + background: secondaryColor, }, '.list-table-row .list-table-cell-a, .list-table-row .list-table-cell-b': { 'border-top': border, @@ -55,7 +88,7 @@ export function buildStyles({ textColor, backgroundColor, linkColor, linkColorHo 'background-size': '25px 25px', }, '.list-icons-item': { - 'background-color': shadeColor, + 'background-color': secondaryColor, }, '.source-gdrive .side-bar-menu a, .source-gphotos .side-bar-menu a': { color: linkColor, @@ -80,5 +113,21 @@ export function buildStyles({ textColor, backgroundColor, linkColor, linkColorHo color: linkColorHover, background: 'none', }, + 'input[type=submit], .button, button': { + color: secondaryForegroundColor, + background: secondaryColor, + 'box-shadow': 'none', + border: 'none', + 'border-radius': radius, + }, + 'input[type=submit]:hover, .button:hover, button:hover': { + background: secondaryHover, + }, + '.text-field, input[type=search], input[type=text], input[type=url], textarea': { + color: secondaryForegroundColor, + 'border-radius': radius, + background: secondaryColor, + border, + }, }); } diff --git a/blocks/ExternalSource/external-source.css b/blocks/ExternalSource/external-source.css index 1739a0588..53cec0065 100644 --- a/blocks/ExternalSource/external-source.css +++ b/blocks/ExternalSource/external-source.css @@ -3,12 +3,15 @@ lr-external-source { flex-direction: column; width: 100%; height: 100%; - background-color: var(--clr-background-light); + background-color: var(--uc-background); overflow: hidden; } -lr-modal lr-external-source { - width: min(calc(var(--modal-max-w) - var(--gap-mid) * 2), calc(100vw - var(--gap-mid) * 2)); +[lr-modal] lr-external-source { + width: min( + calc(var(--uc-dialog-max-width) - var(--uc-padding) * 2), + calc(var(--uc-dialog-max-width) - var(--uc-padding) * 2) + ); height: var(--modal-content-height-fill, 100%); max-height: var(--modal-max-content-height); } @@ -22,7 +25,7 @@ lr-external-source > .content { @media only screen and (max-width: 430px) { lr-external-source { - width: calc(100vw - var(--gap-mid) * 2); + width: calc(100vw - var(--uc-padding) * 2); height: var(--modal-content-height-fill, 100%); } } @@ -40,12 +43,12 @@ lr-external-source .iframe-wrapper { lr-external-source .toolbar { display: grid; - grid-gap: var(--gap-mid); + grid-gap: var(--uc-padding); grid-template-columns: max-content 1fr max-content max-content; align-items: center; width: 100%; - padding: var(--gap-mid); - border-top: var(--border-light); + padding: var(--uc-padding); + border-top: 1px solid var(--uc-border); } lr-external-source .back-btn { @@ -54,9 +57,9 @@ lr-external-source .back-btn { lr-external-source .selected-counter { display: flex; - grid-gap: var(--gap-mid); + grid-gap: var(--uc-padding); align-items: center; justify-content: space-between; - padding: var(--gap-mid); - color: var(--clr-txt-light); + padding: var(--uc-padding); + color: var(--uc-muted-foreground); } diff --git a/blocks/FileItem/FileItem.js b/blocks/FileItem/FileItem.js index e0337f26d..9ff9f7a81 100644 --- a/blocks/FileItem/FileItem.js +++ b/blocks/FileItem/FileItem.js @@ -1,13 +1,13 @@ -import { shrinkFile } from '@uploadcare/image-shrink'; // @ts-check import { CancelError, uploadFile } from '@uploadcare/upload-client'; +import { shrinkFile } from '@uploadcare/image-shrink'; import { ActivityBlock } from '../../abstract/ActivityBlock.js'; import { UploaderBlock } from '../../abstract/UploaderBlock.js'; import { createCdnUrl, createCdnUrlModifiers, createOriginalUrl } from '../../utils/cdn-utils.js'; -import { parseShrink } from '../../utils/parseShrink.js'; import { fileCssBg } from '../svg-backgrounds/svg-backgrounds.js'; import { debounce } from '../utils/debounce.js'; import { generateThumb } from '../utils/resizeImage.js'; +import { parseShrink } from '../../utils/parseShrink.js'; const FileItemState = Object.freeze({ FINISHED: Symbol(0), @@ -75,7 +75,7 @@ export class FileItem extends UploaderBlock { } _reset() { - for (const sub of this._entrySubs) { + for (let sub of this._entrySubs) { sub.remove(); } @@ -90,7 +90,7 @@ export class FileItem extends UploaderBlock { * @param {IntersectionObserverEntry[]} entries */ _observerCallback(entries) { - const [entry] = entries; + let [entry] = entries; this._isIntersecting = entry.isIntersecting; if (entry.isIntersecting && !this._renderedOnce) { @@ -109,7 +109,7 @@ export class FileItem extends UploaderBlock { if (!this._entry) { return; } - const entry = this._entry; + let entry = this._entry; let state = FileItemState.IDLE; if (entry.getValue('errors').length > 0) { @@ -128,17 +128,17 @@ export class FileItem extends UploaderBlock { if (!this._entry) { return; } - const entry = this._entry; + let entry = this._entry; if (entry.getValue('fileInfo') && entry.getValue('isImage')) { - const size = this.cfg.thumbSize; - const thumbUrl = this.proxyUrl( + let size = this.cfg.thumbSize; + let thumbUrl = this.proxyUrl( createCdnUrl( createOriginalUrl(this.cfg.cdnCname, this._entry.getValue('uuid')), createCdnUrlModifiers(entry.getValue('cdnUrlModifiers'), `scale_crop/${size}x${size}/center`), ), ); - const currentThumbUrl = entry.getValue('thumbUrl'); + let currentThumbUrl = entry.getValue('thumbUrl'); if (currentThumbUrl !== thumbUrl) { entry.setValue('thumbUrl', thumbUrl); currentThumbUrl?.startsWith('blob:') && URL.revokeObjectURL(currentThumbUrl); @@ -152,14 +152,14 @@ export class FileItem extends UploaderBlock { if (entry.getValue('file')?.type.includes('image')) { try { - const thumbUrl = await generateThumb(entry.getValue('file'), this.cfg.thumbSize); + let thumbUrl = await generateThumb(entry.getValue('file'), this.cfg.thumbSize); entry.setValue('thumbUrl', thumbUrl); } catch (err) { - const color = window.getComputedStyle(this).getPropertyValue('--clr-generic-file-icon'); + let color = window.getComputedStyle(this).getPropertyValue('--uc-muted-foreground'); entry.setValue('thumbUrl', fileCssBg(color)); } } else { - const color = window.getComputedStyle(this).getPropertyValue('--clr-generic-file-icon'); + let color = window.getComputedStyle(this).getPropertyValue('--uc-muted-foreground'); entry.setValue('thumbUrl', fileCssBg(color)); } } @@ -170,7 +170,7 @@ export class FileItem extends UploaderBlock { * @param {(value: any) => void} handler */ _subEntry(prop, handler) { - const sub = this._entry.subscribe( + let sub = this._entry.subscribe( prop, /** @param {any} value */ (value) => { if (this.isConnected) { @@ -189,7 +189,7 @@ export class FileItem extends UploaderBlock { this._reset(); /** @type {import('../../abstract/TypedData.js').TypedData} */ - const entry = this.uploadCollection?.read(id); + let entry = this.uploadCollection?.read(id); this._entry = entry; if (!entry) { @@ -251,13 +251,13 @@ export class FileItem extends UploaderBlock { this.subConfigValue('useCloudImageEditor', () => this._debouncedCalculateState()); this.onclick = () => { - for (const instance of FileItem.activeInstances) { - if (instance === this) { - instance.setAttribute('focused', ''); + FileItem.activeInstances.forEach((inst) => { + if (inst === this) { + inst.setAttribute('focused', ''); } else { - instance.removeAttribute('focused'); + inst.removeAttribute('focused'); } - } + }); }; this.sub( @@ -310,8 +310,6 @@ export class FileItem extends UploaderBlock { /** @private */ this._observer = new window.IntersectionObserver(this._observerCallback.bind(this), { - root: this.parentElement, - rootMargin: '50% 0px 50% 0px', threshold: [0, 1], }); this._observer.observe(this); @@ -337,7 +335,7 @@ export class FileItem extends UploaderBlock { } async upload() { - const entry = this._entry; + let entry = this._entry; if (!this.uploadCollection.read(entry.uid)) { return; @@ -356,7 +354,7 @@ export class FileItem extends UploaderBlock { entry.setValue('errors', []); try { - const abortController = new AbortController(); + let abortController = new AbortController(); entry.setValue('abortController', abortController); const uploadTask = async () => { @@ -374,7 +372,7 @@ export class FileItem extends UploaderBlock { source: entry.getValue('source'), onProgress: (progress) => { if (progress.isComputable) { - const percentage = progress.value * 100; + let percentage = progress.value * 100; entry.setValue('uploadProgress', percentage); } }, @@ -386,7 +384,7 @@ export class FileItem extends UploaderBlock { }; /** @type {import('@uploadcare/upload-client').UploadcareFile} */ - const fileInfo = await this.$['*uploadQueue'].add(uploadTask); + let fileInfo = await this.$['*uploadQueue'].add(uploadTask); entry.setMultipleValues({ fileInfo, isUploading: false, @@ -436,10 +434,15 @@ FileItem.template = /* HTML */ ` {{errorText}} - + - + diff --git a/blocks/FileItem/file-item.css b/blocks/FileItem/file-item.css index 30c2157d8..2a800c41e 100644 --- a/blocks/FileItem/file-item.css +++ b/blocks/FileItem/file-item.css @@ -1,23 +1,31 @@ lr-file-item { + --uc-file-item-gap: 4px; + --uc-file-item-height: calc(var(--uc-preview-size) + var(--uc-padding) * 2 + var(--uc-file-item-gap)); + display: block; + content-visibility: auto; + height: var(--uc-file-item-height); + contain-intrinsic-size: auto var(--uc-file-item-height); + overflow: hidden; +} + +lr-file-item:last-of-type { + --uc-file-item-gap: 0; } + lr-file-item > .inner { position: relative; display: grid; - grid-template-columns: 32px 1fr max-content; - gap: var(--gap-min); + grid-template-columns: var(--uc-preview-size) 1fr max-content; + gap: 2px; align-items: center; - margin-bottom: var(--gap-small); - padding: var(--gap-mid); + margin-bottom: var(--uc-file-item-gap); + padding: var(--uc-padding); overflow: hidden; - font-size: 0.95em; - background-color: var(--clr-background); - border-radius: var(--border-radius-element); - transition: var(--transition-duration); -} - -lr-file-item:last-of-type > .inner { - margin-bottom: 0; + font-size: 0.925em; + background-color: var(--uc-muted); + border-radius: var(--uc-radius); + transition: background-color var(--uc-transition); } lr-file-item > .inner[focused] { @@ -29,18 +37,18 @@ lr-file-item > .inner[uploading] .edit-btn { } lr-file-item > :where(.inner[failed], .inner[limit-overflow]) { - background-color: var(--clr-error-lightest); + background-color: var(--uc-destructive); } lr-file-item .thumb { position: relative; display: inline-flex; - width: var(--ui-size); - height: var(--ui-size); - background-color: var(--clr-shade-lv1); + width: var(--uc-preview-size); + height: var(--uc-preview-size); + background-color: var(--uc-secondary); background-position: center center; background-size: cover; - border-radius: var(--border-radius-thumb); + border-radius: var(--uc-radius); } lr-file-item .file-name-wrapper { @@ -49,11 +57,10 @@ lr-file-item .file-name-wrapper { align-items: flex-start; justify-content: center; max-width: 100%; - padding-right: var(--gap-mid); - padding-left: var(--gap-mid); + padding-right: var(--uc-padding); + padding-left: var(--uc-padding); overflow: hidden; - color: var(--clr-txt-light); - transition: color var(--transition-duration); + color: var(--uc-muted-foreground); } lr-file-item .file-name { @@ -65,36 +72,37 @@ lr-file-item .file-name { lr-file-item .file-error { display: none; - color: var(--clr-error); + color: var(--uc-destructive-foreground); font-size: 0.85em; - line-height: 130%; } lr-file-item button.remove-btn, lr-file-item button.edit-btn { - color: var(--clr-txt-lightest) !important; /* todo: remove after refactoring of common.css */ + color: var(--uc-muted-foreground); } -lr-file-item button.upload-btn { - display: none; +lr-file-item button svg { + pointer-events: none; } -lr-file-item button:hover { - color: var(--clr-txt-light); +lr-file-item button.upload-btn { + display: none; } lr-file-item .badge { position: absolute; - top: calc(var(--ui-size) * -0.13); - right: calc(var(--ui-size) * -0.13); - width: calc(var(--ui-size) * 0.44); - height: calc(var(--ui-size) * 0.44); - color: var(--clr-background-light); - background-color: var(--clr-txt); + bottom: 2px; + right: 2px; + width: 14px; + height: 14px; + color: var(--uc-background); + background-color: var(--uc-foreground); border-radius: 50%; transform: scale(0.3); opacity: 0; - transition: var(--transition-duration) ease; + transition: + opacity var(--uc-transition), + transform var(--uc-transition); display: flex; justify-content: center; align-items: center; @@ -105,12 +113,8 @@ lr-file-item > .inner:where([failed], [limit-overflow], [finished]) .badge { opacity: 1; } -lr-file-item > .inner[finished] .badge { - background-color: var(--clr-confirm); -} - lr-file-item > .inner:where([failed], [limit-overflow]) .badge { - background-color: var(--clr-error); + background-color: var(--uc-destructive-foreground); } lr-file-item > .inner:where([failed], [limit-overflow]) .file-error { @@ -124,13 +128,14 @@ lr-file-item .badge lr-icon svg { } lr-file-item .progress-bar { + opacity: 0.5; top: calc(100% - 2px); height: 2px; } lr-file-item .file-actions { display: flex; - gap: var(--gap-min); + gap: 2px; align-items: center; justify-content: center; } diff --git a/blocks/FilePreview/FilePreview.js b/blocks/FilePreview/FilePreview.js deleted file mode 100644 index b21963313..000000000 --- a/blocks/FilePreview/FilePreview.js +++ /dev/null @@ -1,51 +0,0 @@ -import { Block } from '../../abstract/Block.js'; -import { TRANSPARENT_PIXEL_SRC } from '../../utils/transparentPixelSrc.js'; -import { checkerboardCssBg } from '../svg-backgrounds/svg-backgrounds.js'; - -export class FilePreview extends Block { - init$ = { - ...this.init$, - checkerboard: false, - src: TRANSPARENT_PIXEL_SRC, - }; - - initCallback() { - super.initCallback(); - this.sub('checkerboard', () => { - this.style.backgroundImage = this.hasAttribute('checkerboard') ? `url(${checkerboardCssBg()})` : 'unset'; - }); - } - - destroyCallback() { - super.destroyCallback(); - URL.revokeObjectURL(this._lastObjectUrl); - } - - /** @param {HTMLImageElement} img */ - setImage(img) { - this.$.src = img.src; - } - - /** @param {File} imgFile */ - setImageFile(imgFile) { - const url = URL.createObjectURL(imgFile); - this.$.src = url; - this._lastObjectUrl = url; - } - - /** @param {String} url */ - setImageUrl(url) { - this.$.src = url; - } - - clear() { - URL.revokeObjectURL(this._lastObjectUrl); - this.$.src = TRANSPARENT_PIXEL_SRC; - } -} - -FilePreview.template = /* HTML */ ` `; - -FilePreview.bindAttributes({ - checkerboard: 'checkerboard', -}); diff --git a/blocks/FilePreview/file-preview.css b/blocks/FilePreview/file-preview.css deleted file mode 100644 index 266baa4c5..000000000 --- a/blocks/FilePreview/file-preview.css +++ /dev/null @@ -1,27 +0,0 @@ -lr-file-preview { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; -} - -lr-file-preview > lr-img { - display: contents; -} - -lr-file-preview > lr-img > .img-view { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: 100%; - max-width: 100%; - height: 100%; - max-height: 100%; - object-fit: scale-down; -} diff --git a/blocks/Icon/icon.css b/blocks/Icon/icon.css index 8259f816f..032c266d5 100644 --- a/blocks/Icon/icon.css +++ b/blocks/Icon/icon.css @@ -2,11 +2,11 @@ lr-icon { display: inline-flex; align-items: center; justify-content: center; - width: var(--ui-size); - height: var(--ui-size); + width: var(--uc-button-size); + height: var(--uc-button-size); } lr-icon svg { - width: calc(var(--ui-size) / 2); - height: calc(var(--ui-size) / 2); + width: calc(var(--uc-button-size) / 2); + height: calc(var(--uc-button-size) / 2); } diff --git a/blocks/LiveHtml/LiveHtml.js b/blocks/LiveHtml/LiveHtml.js deleted file mode 100644 index 8386e40c3..000000000 --- a/blocks/LiveHtml/LiveHtml.js +++ /dev/null @@ -1,279 +0,0 @@ -import { Block } from '../../abstract/Block.js'; - -const INIT_HTML = /* HTML */ ` - - - - - - - Document - - - CONTENT - - -`.trim(); - -// biome-ignore lint/complexity/noStaticOnlyClass: It will be removed soon -class Caret { - static getPosition(parentElement) { - const selection = window.getSelection(); - let charCount = -1; - let node; - - if (selection.focusNode) { - if (Caret._isChildOf(selection.focusNode, parentElement)) { - node = selection.focusNode; - charCount = selection.focusOffset; - - while (node) { - if (node === parentElement) { - break; - } - if (node.previousSibling) { - node = node.previousSibling; - charCount += node.textContent.length; - } else { - node = node.parentNode; - if (node === null) { - break; - } - } - } - } - } - return charCount; - } - - static setPosition(chars, element) { - if (chars >= 0) { - const selection = window.getSelection(); - - const range = Caret._createRange(element, { - count: chars, - }); - - if (range) { - range.collapse(false); - selection.removeAllRanges(); - selection.addRange(range); - } - } - } - - static _createRange(node, chars, range) { - if (!range) { - // biome-ignore lint/style/noParameterAssign: It will be removed soon - range = document.createRange(); - range.selectNode(node); - range.setStart(node, 0); - } - - if (chars.count === 0) { - range.setEnd(node, chars.count); - } else if (node && chars.count > 0) { - if (node.nodeType === Node.TEXT_NODE) { - if (node.textContent.length < chars.count) { - chars.count -= node.textContent.length; - } else { - range.setEnd(node, chars.count); - chars.count = 0; - } - } else { - for (let lp = 0; lp < node.childNodes.length; lp++) { - // biome-ignore lint/style/noParameterAssign: It will be removed soon - range = Caret._createRange(node.childNodes[lp], chars, range); - - if (chars.count === 0) { - break; - } - } - } - } - return range; - } - - static _isChildOf(node, parentElement) { - while (node !== null) { - if (node === parentElement) { - return true; - } - // biome-ignore lint/style/noParameterAssign: It will be removed soon - node = node.parentNode; - } - return false; - } -} - -const headerHtml = /* HTML */ ` - -`; - -export class LiveHtml extends Block { - async hl() { - const offset = Caret.getPosition(this.ref.editor); - - this.ref.editor.textContent = this.ref.editor.textContent; - - let html = this.ref.editor.textContent; - const hljs = await import( - 'https://cdn.skypack.dev/pin/highlight.js@v11.6.0-4W1e4sNTmpsDP0C1l7xy/mode=imports,min/optimized/highlightjs.js' - ); - // @ts-ignore - html = hljs.default.highlight(this.ref.editor.textContent, { language: 'html' }).value; - this.ref.editor.innerHTML = html; - - Caret.setPosition(offset, this.ref.editor); - // this.ref.editor.focus(); - } - - sync() { - this.hl(); - if (this._updTimeout) { - window.clearTimeout(this._updTimeout); - } - this._updTimeout = window.setTimeout(() => { - // @ts-ignore - this.ref.vp.srcdoc = headerHtml + (this.importmapHtml || '') + this.ref.editor.textContent; - if (this.hasAttribute('console-output')) { - /** @type {Window} */ - // @ts-ignore - const docWin = this.ref.vp.contentWindow; - this.ref.vp.onload = () => { - console.dirxml(docWin.document.body); - }; - } - }, 300); - } - - init$ = { - ...this.init$, - src: '', - code: INIT_HTML, - spellcheck: false, - onInput: () => { - this.sync(); - }, - onKeydown: (e) => { - if (e.keyCode === 13) { - e.preventDefault(); - document.execCommand('insertHTML', false, '\n'); - } else if (e.keyCode === 9) { - e.preventDefault(); - document.execCommand('insertHTML', false, ' '); - } - }, - onNewTabClick: () => { - const url = new URL(document.location.toString()); - url.hash = ''; - const baseUrl = url.toString(); - - const code = ` - - - - -${this.ref.vp.srcdoc} - - `; - const winUrl = URL.createObjectURL(new Blob([code], { type: 'text/html' })); - window.open(winUrl); - }, - // onPaste: (e) => { - // e.preventDefault(); - // let text = e.clipboardData.getData('text/plain'); - // document.execCommand('insertText', false, text); - // }, - }; - - connectedCallback() { - if (this.innerHTML.trim()) { - const lines = this.innerHTML.split('\n'); - let commonTabSize = 1000; - // biome-ignore lint/complexity/noForEach: It will be removed soon - lines.forEach((line) => { - if (!line.trim()) { - return; - } - if (!line.startsWith(' ')) { - commonTabSize = 0; - return; - } - const tabs = line.match(/^ +/); - if (tabs) { - commonTabSize = Math.min(commonTabSize, tabs[0].length); - } - }); - /** @private */ - this.__innerHtml = lines - .map((line) => { - for (let i = 0; i < commonTabSize; i++) { - if (line.startsWith(' ')) { - // biome-ignore lint/style/noParameterAssign: It will be removed soon - line = line.replace(' ', ''); - } - } - return line; - }) - .join('\n'); - this.innerHTML = ''; - } - super.connectedCallback(); - } - - initCallback() { - const docImportMap = document.querySelector('script[type="importmap"]'); - if (docImportMap) { - let shimScriptHtml = ''; - const shimScriptEl = document.querySelector('script[src*="es-module-shims.js"]'); - if (shimScriptEl) { - shimScriptHtml = shimScriptEl.outerHTML; - } - this.importmapHtml = shimScriptHtml + docImportMap.outerHTML; - } - if (this.hasAttribute('src')) { - this.sub('src', (val) => { - if (val) { - window.fetch(val).then(async (resp) => { - const code = await resp.text(); - this.$.code = code; - this.sync(); - }); - } else { - this.$.code = INIT_HTML; - } - }); - } else if (this.__innerHtml) { - this.$.code = this.__innerHtml; - this.sync(); - } else { - this.$.code = INIT_HTML; - } - } -} - -LiveHtml.bindAttributes({ - src: 'src', -}); - -LiveHtml.template = /* HTML */ ` - - - Open in the new tab -`; diff --git a/blocks/LiveHtml/live-html.css b/blocks/LiveHtml/live-html.css deleted file mode 100644 index 9d43e2dfd..000000000 --- a/blocks/LiveHtml/live-html.css +++ /dev/null @@ -1,68 +0,0 @@ -lr-live-html { - position: relative; - display: grid; - grid-template-columns: 50% 50%; - box-shadow: 0 5px 16px rgb(0 0 0 / 60%); -} - -lr-live-html [contenteditable] { - padding: 20px; - overflow: auto; - color: rgb(255 255 255); - font-size: 14px; - font-family: monospace; - white-space: pre; - background-color: #000; - outline: none; -} - -lr-live-html [contenteditable] .hljs-string { - color: rgb(251, 182, 79); -} -lr-live-html [contenteditable] .hljs-comment { - color: rgb(149, 149, 149); - font-style: italic; -} -lr-live-html [contenteditable] .hljs-attr { - color: rgb(138, 218, 172); -} -lr-live-html [contenteditable] .hljs-function { - color: rgb(239, 235, 149); -} -lr-live-html [contenteditable] .hljs-variable { - color: rgb(121, 183, 255); -} -lr-live-html [contenteditable] .hljs-title { - color: rgb(180, 243, 255); -} -lr-live-html [contenteditable] .hljs-property { - color: rgb(238, 131, 252); -} -lr-live-html [contenteditable] .hljs-keyword { - color: rgb(254, 165, 176); -} -lr-live-html [contenteditable] .hljs-tag { - color: rgb(254, 165, 176); -} -lr-live-html [contenteditable] .hljs-name { - color: rgb(165, 245, 254); -} - -lr-live-html iframe { - display: block; - width: 100%; - height: 100%; - background-color: #fff; - border: 0; -} - -lr-live-html > .open-new-tab-btn { - position: absolute; - top: 6px; - left: 6px; - display: none; -} - -lr-live-html:hover > .open-new-tab-btn { - display: block; -} diff --git a/blocks/Modal/Modal.js b/blocks/Modal/Modal.js index e911c564a..141b6a5e8 100644 --- a/blocks/Modal/Modal.js +++ b/blocks/Modal/Modal.js @@ -2,6 +2,7 @@ import { Block } from '../../abstract/Block.js'; export class Modal extends Block { + static styleAttrs = [...super.styleAttrs, 'lr-modal']; static StateConsumerScope = 'modal'; constructor() { diff --git a/blocks/Modal/modal.css b/blocks/Modal/modal.css index 593ae5200..ced041b1d 100644 --- a/blocks/Modal/modal.css +++ b/blocks/Modal/modal.css @@ -1,9 +1,11 @@ -lr-modal { - --modal-max-content-height: calc(var(--uploadcare-blocks-window-height, 100vh) - 4 * var(--gap-mid) - var(--ui-size)); +:where([lr-modal]) { + --modal-max-content-height: calc( + var(--uploadcare-blocks-window-height, 100vh) - 4 * var(--uc-padding) - var(--uc-button-size) + ); --modal-content-height-fill: var(--uploadcare-blocks-window-height, 100vh); } -lr-modal[dialog-fallback] { +:where([lr-modal])[dialog-fallback] { --lr-z-max: 2147483647; position: fixed; @@ -17,12 +19,12 @@ lr-modal[dialog-fallback] { inset: 0; } -lr-modal[dialog-fallback] dialog[open] { +:where([lr-modal])[dialog-fallback] dialog[open] { z-index: var(--lr-z-max); pointer-events: auto; } -lr-modal[dialog-fallback] dialog[open] + .backdrop { +:where([lr-modal])[dialog-fallback] dialog[open] + .backdrop { position: fixed; top: 0px; left: 0px; @@ -31,58 +33,60 @@ lr-modal[dialog-fallback] dialog[open] + .backdrop { justify-content: center; width: 100vw; height: 100vh; - background-color: var(--clr-curtain); + background-color: oklch(0 0 0 / 0.1); pointer-events: auto; } -lr-modal[strokes][dialog-fallback] dialog[open] + .backdrop { +:where([lr-modal])[strokes][dialog-fallback] dialog[open] + .backdrop { background-image: var(--modal-backdrop-background-image); } @supports selector(dialog::backdrop) { - lr-modal > dialog::backdrop { + :where([lr-modal]) > dialog::backdrop { /* backdrop don't inherit theme properties */ - background-color: rgba(0, 0, 0, 10%); + background-color: oklch(0 0 0 / 0.1); } - lr-modal[strokes] > dialog::backdrop { + :where([lr-modal])[strokes] > dialog::backdrop { /* TODO: it's not working, fix it */ background-image: var(--modal-backdrop-background-image); } } -lr-modal > dialog[open] { +:where([lr-modal]) > dialog[open] { transform: translateY(0px); visibility: visible; opacity: 1; } -lr-modal > dialog:not([open]) { +:where([lr-modal]) > dialog:not([open]) { transform: translateY(20px); visibility: hidden; opacity: 0; } -lr-modal > dialog { +:where([lr-modal]) > dialog { display: flex; flex-direction: column; /* there was `fit-content` but it doesn't reduce width after activity change */ width: max-content; - max-width: min(calc(100% - var(--gap-mid) * 2), calc(var(--modal-max-w) - var(--gap-mid) * 2)); - min-height: var(--ui-size); - max-height: calc(var(--modal-max-h) - var(--gap-mid) * 2); + max-width: min(calc(100% - var(--uc-padding) * 2), calc(var(--uc-dialog-max-width) - var(--uc-padding) * 2)); + min-height: var(--uc-button-size); + max-height: calc(var(--uc-dialog-max-height) - var(--uc-padding) * 2); margin: auto; padding: 0; overflow: hidden; - background-color: var(--clr-background-light); + background-color: var(--uc-background); border: 0; - border-radius: var(--border-radius-frame); - box-shadow: var(--modal-shadow); - transition: transform calc(var(--transition-duration) * 2); + border-radius: calc(var(--uc-radius) * 1.75); + box-shadow: var(--uc-dialog-shadow); + transition: + transform 0.4s ease, + opacity 0.4s ease; } @media only screen and (max-width: 430px), only screen and (max-height: 600px) { - lr-modal > dialog > .content { + :where([lr-modal]) > dialog > .content { height: var(--modal-max-content-height); } } diff --git a/blocks/ProgressBar/progress-bar.css b/blocks/ProgressBar/progress-bar.css index 896e55097..7a82eaeb4 100644 --- a/blocks/ProgressBar/progress-bar.css +++ b/blocks/ProgressBar/progress-bar.css @@ -12,7 +12,7 @@ lr-progress-bar { lr-progress-bar .progress { width: calc(var(--l-width) * 1%); height: 100%; - background-color: var(--clr-accent-light); + background-color: var(--uc-primary); transform: translateX(0); opacity: 1; transition: diff --git a/blocks/ProgressBarCommon/progress-bar-common.css b/blocks/ProgressBarCommon/progress-bar-common.css index 297bcb164..a9de92ebd 100644 --- a/blocks/ProgressBarCommon/progress-bar-common.css +++ b/blocks/ProgressBarCommon/progress-bar-common.css @@ -5,8 +5,8 @@ lr-progress-bar-common { left: 0; z-index: 10000; display: block; - height: var(--gap-mid); - background-color: var(--clr-background); + height: 10px; + background-color: var(--uc-background); transition: opacity 0.3s; } diff --git a/blocks/Range/range.css b/blocks/Range/range.css index 418a698fc..d190cd664 100644 --- a/blocks/Range/range.css +++ b/blocks/Range/range.css @@ -3,7 +3,7 @@ lr-range { display: inline-flex; align-items: center; justify-content: center; - height: var(--ui-size); + height: var(--uc-button-size); } lr-range datalist { diff --git a/blocks/Select/Select.js b/blocks/Select/Select.js index 036e32a13..3af9dd81c 100644 --- a/blocks/Select/Select.js +++ b/blocks/Select/Select.js @@ -34,10 +34,4 @@ export class Select extends Block { } } -Select.template = /* HTML */ ` - - {{currentText}} - - - -`; +Select.template = /* HTML */ ` `; diff --git a/blocks/Select/select.css b/blocks/Select/select.css index f688b1d29..b4558f913 100644 --- a/blocks/Select/select.css +++ b/blocks/Select/select.css @@ -2,20 +2,21 @@ lr-select { display: inline-flex; } -lr-select > button { +lr-select select { position: relative; display: inline-flex; align-items: center; - padding-right: 0 !important; /* todo: get rid of important */ - color: var(--clr-btn-txt-secondary); - background-color: var(--clr-btn-bgr-secondary); - box-shadow: var(--shadow-btn-secondary); -} - -lr-select > button > select { - position: absolute; - display: block; - width: 100%; - height: 100%; - opacity: 0; + justify-content: center; + height: var(--uc-button-size); + padding: 0 14px; + font-size: 1em; + font-family: inherit; + white-space: nowrap; + border: none; + border-radius: var(--uc-radius); + cursor: pointer; + user-select: none; + transition: background-color var(--uc-transition); + color: var(--uc-secondary-foreground); + background-color: var(--uc-secondary); } diff --git a/blocks/SimpleBtn/SimpleBtn.js b/blocks/SimpleBtn/SimpleBtn.js index 31121093b..236ea9668 100644 --- a/blocks/SimpleBtn/SimpleBtn.js +++ b/blocks/SimpleBtn/SimpleBtn.js @@ -3,6 +3,7 @@ import { UploaderBlock } from '../../abstract/UploaderBlock.js'; import { asBoolean } from '../Config/normalizeConfigValue.js'; export class SimpleBtn extends UploaderBlock { + static styleAttrs = [...super.styleAttrs, 'lr-simple-btn']; couldBeCtxOwner = true; constructor() { super(); diff --git a/blocks/SimpleBtn/simple-btn.css b/blocks/SimpleBtn/simple-btn.css index 0c8e3a756..3173e637c 100644 --- a/blocks/SimpleBtn/simple-btn.css +++ b/blocks/SimpleBtn/simple-btn.css @@ -1,32 +1,37 @@ -lr-simple-btn { +:where([lr-simple-btn]) { position: relative; display: inline-flex; } -lr-simple-btn button { - padding-left: 0.2em !important; - color: var(--clr-btn-txt-secondary); - background-color: var(--clr-btn-bgr-secondary); - box-shadow: var(--shadow-btn-secondary); +:where([lr-simple-btn]) button { + height: auto; + gap: 0.5em; + padding: var(--uc-simple-btn-padding); + background-color: var(--uc-simple-btn); + color: var(--uc-simple-btn-foreground); + font-size: var(--uc-simple-btn-font-size); + font-family: var(--uc-simple-btn-font-family); } -lr-simple-btn button lr-icon svg { - transform: scale(0.8); +:where([lr-simple-btn]) button lr-icon { + width: auto; + height: auto; } -lr-simple-btn button:hover { - background-color: var(--clr-btn-bgr-secondary-hover); +:where([lr-simple-btn]) button lr-icon svg { + width: 0.9em; + height: 0.9em; } -lr-simple-btn button:active { - background-color: var(--clr-btn-bgr-secondary-active); +:where([lr-simple-btn]) button:hover { + background-color: var(--uc-simple-btn-hover); } -lr-simple-btn > lr-drop-area { +:where([lr-simple-btn]) > lr-drop-area { display: contents; } -lr-simple-btn .visual-drop-area { +:where([lr-simple-btn]) .visual-drop-area { position: absolute; top: 0px; left: 0px; @@ -35,55 +40,25 @@ lr-simple-btn .visual-drop-area { justify-content: center; width: 100%; height: 100%; - padding: var(--gap-min); - border: var(--border-dashed); + padding: var(--uc-simple-btn-padding); + background-color: transparent; + color: transparent; + font-size: var(--uc-simple-btn-font-size); + border: 1px dashed var(--uc-simple-btn-foreground); border-radius: inherit; opacity: 0; - transition: - border-color var(--transition-duration) ease, - background-color var(--transition-duration) ease, - opacity var(--transition-duration) ease; + transition: opacity var(--uc-transition); } -lr-simple-btn .visual-drop-area::before { - position: absolute; - top: 0px; - left: 0px; - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - color: var(--clr-txt-light); - background-color: var(--clr-background); - border-radius: inherit; -} - -lr-simple-btn > lr-drop-area[drag-state='active'] .visual-drop-area { - background-color: var(--clr-accent-lightest); +:where([lr-simple-btn]) > lr-drop-area[drag-state='active'] .visual-drop-area { opacity: 1; } -lr-simple-btn > lr-drop-area[drag-state='inactive'] .visual-drop-area { - background-color: var(--clr-shade-lv1); +:where([lr-simple-btn]) > lr-drop-area[drag-state='inactive'] .visual-drop-area { opacity: 0; } -lr-simple-btn > lr-drop-area[drag-state='near'] .visual-drop-area { - background-color: var(--clr-accent-lightest); - border-color: var(--clr-accent-light); +:where([lr-simple-btn]) > lr-drop-area[drag-state='near'] .visual-drop-area { opacity: 1; } -lr-simple-btn > lr-drop-area[drag-state='over'] .visual-drop-area { - background-color: var(--clr-accent-lightest); - border-color: var(--clr-accent); +:where([lr-simple-btn]) > lr-drop-area[drag-state='over'] .visual-drop-area { opacity: 1; } - -lr-simple-btn - > :where(lr-drop-area[drag-state='active'], lr-drop-area[drag-state='near'], lr-drop-area[drag-state='over']) - button { - box-shadow: none; -} - -lr-simple-btn > lr-drop-area::after { - content: ''; -} diff --git a/blocks/SourceBtn/SourceBtn.js b/blocks/SourceBtn/SourceBtn.js index 929d0d1f9..36283c08a 100644 --- a/blocks/SourceBtn/SourceBtn.js +++ b/blocks/SourceBtn/SourceBtn.js @@ -80,7 +80,6 @@ export class SourceBtn extends UploaderBlock { super.initCallback(); this.initTypes(); - this.setAttribute('role', 'button'); this.defineAccessor( 'type', /** @param {string} val */ @@ -133,9 +132,12 @@ export class SourceBtn extends UploaderBlock { }; } } + SourceBtn.template = /* HTML */ ` - - + + + + `; SourceBtn.bindAttributes({ // @ts-expect-error symbiote types bug diff --git a/blocks/SourceBtn/source-btn.css b/blocks/SourceBtn/source-btn.css index 1412153a5..d208b300d 100644 --- a/blocks/SourceBtn/source-btn.css +++ b/blocks/SourceBtn/source-btn.css @@ -1,32 +1,35 @@ -lr-source-btn { +lr-source-btn > button { display: flex; align-items: center; - margin-bottom: var(--gap-min); - padding: var(--gap-min) var(--gap-mid); - color: var(--clr-txt-mid); - border-radius: var(--border-radius-element); + margin-bottom: 2px; + padding: 2px var(--uc-padding); + color: var(--uc-foreground); + border-radius: var(--uc-radius); cursor: pointer; - transition-duration: var(--transition-duration); - transition-property: background-color, color; + transition: + background-color var(--uc-transition), + color var(--uc-transition); user-select: none; + width: 100%; + background-color: unset; + height: unset; } -lr-source-btn:hover { - color: var(--clr-accent); - background-color: var(--clr-accent-lightest); +lr-source-btn:last-child > button { + margin-bottom: 0; } -lr-source-btn:active { - color: var(--clr-accent); - background-color: var(--clr-accent-light); +lr-source-btn > button:hover { + color: var(--uc-primary); + background-color: var(--uc-primary-transparent); } lr-source-btn lr-icon { display: inline-flex; flex-grow: 1; justify-content: center; - min-width: var(--ui-size); - margin-right: var(--gap-mid); + min-width: var(--uc-button-size); + margin-right: var(--uc-padding); opacity: 0.8; } @@ -35,7 +38,7 @@ lr-source-btn .txt { align-items: center; box-sizing: border-box; width: 100%; - height: var(--ui-size); + height: var(--uc-button-size); padding: 0; white-space: nowrap; border: none; diff --git a/blocks/StartFrom/start-from.css b/blocks/StartFrom/start-from.css index a7e518f3e..889319b44 100644 --- a/blocks/StartFrom/start-from.css +++ b/blocks/StartFrom/start-from.css @@ -6,13 +6,27 @@ lr-start-from { lr-start-from .content { display: grid; grid-auto-flow: row; - gap: var(--gap-max); + gap: calc(var(--uc-padding) * 2); width: 100%; height: 100%; - padding: var(--gap-max); - background-color: var(--clr-background-light); + padding: calc(var(--uc-padding) * 2); + background-color: var(--uc-background); } -lr-modal lr-start-from { - width: min(calc(var(--modal-normal-w) - var(--gap-mid) * 2), calc(100vw - var(--gap-mid) * 2)); +[lr-modal] lr-start-from { + width: min( + calc(var(--uc-dialog-width) - var(--uc-padding) * 2), + calc(var(--uc-dialog-max-width) - var(--uc-padding) * 2), + calc(100vw - var(--uc-padding) * 2) + ); +} + +[lr-modal] lr-start-from lr-drop-area { + border-radius: var(--uc-radius); +} + +@media only screen and (max-width: 430px) { + [lr-modal] lr-start-from lr-drop-area { + display: none; + } } diff --git a/blocks/Tabs/Tabs.js b/blocks/Tabs/Tabs.js deleted file mode 100644 index a1b676b03..000000000 --- a/blocks/Tabs/Tabs.js +++ /dev/null @@ -1,78 +0,0 @@ -import { create } from '@symbiotejs/symbiote'; -import { Block } from '../../abstract/Block.js'; -import { stringToArray } from '../../utils/stringToArray.js'; - -export class Tabs extends Block { - /** @param {String} tabL10nStr */ - setCurrentTab(tabL10nStr) { - if (!tabL10nStr) { - return; - } - const ctxList = [...this.ref.context.querySelectorAll('[tab-ctx]')]; - for (const ctxEl of ctxList) { - if (ctxEl.getAttribute('tab-ctx') === tabL10nStr) { - ctxEl.removeAttribute('hidden'); - } else { - ctxEl.setAttribute('hidden', ''); - } - } - for (const lStr in this._tabMap) { - if (lStr === tabL10nStr) { - this._tabMap[lStr].setAttribute('current', ''); - } else { - this._tabMap[lStr].removeAttribute('current'); - } - } - } - - initCallback() { - super.initCallback(); - /** - * @private - * @type {Object} - */ - this._tabMap = {}; - this.defineAccessor('tab-list', (/** @type {String} */ val) => { - if (!val) { - return; - } - const tabList = stringToArray(val); - for (const tabL10nStr of tabList) { - const tabEl = create({ - tag: 'div', - attributes: { - class: 'tab', - }, - properties: { - onclick: () => { - this.setCurrentTab(tabL10nStr); - }, - }, - }); - tabEl.textContent = this.l10n(tabL10nStr); - this.ref.row.appendChild(tabEl); - this._tabMap[tabL10nStr] = tabEl; - } - }); - - this.defineAccessor('default', (val) => { - this.setCurrentTab(val); - }); - - if (!this.hasAttribute('default')) { - this.setCurrentTab(Object.keys(this._tabMap)[0]); - } - } -} - -Tabs.bindAttributes({ - 'tab-list': null, - default: null, -}); - -Tabs.template = /* HTML */ ` - - - - -`; diff --git a/blocks/Tabs/tabs.css b/blocks/Tabs/tabs.css deleted file mode 100644 index 12593cf7b..000000000 --- a/blocks/Tabs/tabs.css +++ /dev/null @@ -1,33 +0,0 @@ -lr-tabs { - display: grid; - grid-template-rows: min-content minmax(var(--ui-size), auto); - height: 100%; - overflow: hidden; - color: var(--clr-txt-lightest); -} - -lr-tabs > .tabs-row { - display: flex; - grid-template-columns: minmax(); - background-color: var(--clr-background-light); -} - -lr-tabs > .tabs-context { - overflow-y: auto; -} - -lr-tabs .tabs-row > .tab { - display: flex; - flex-grow: 1; - align-items: center; - justify-content: center; - height: var(--ui-size); - border-bottom: var(--border-light); - cursor: pointer; - transition: var(--transition-duration); -} - -lr-tabs .tabs-row > .tab[current] { - color: var(--clr-txt); - border-color: var(--clr-txt); -} diff --git a/blocks/UploadList/upload-list.css b/blocks/UploadList/upload-list.css index 842eac64b..01fba9992 100644 --- a/blocks/UploadList/upload-list.css +++ b/blocks/UploadList/upload-list.css @@ -4,39 +4,39 @@ lr-upload-list { width: 100%; height: 100%; overflow: hidden; - background-color: var(--clr-background-light); - transition: opacity var(--transition-duration); + background-color: var(--uc-background); + transition: opacity var(--uc-transition); } -lr-modal lr-upload-list { - width: min(calc(var(--modal-normal-w) - var(--gap-mid) * 2), calc(100vw - var(--gap-mid) * 2)); +[lr-modal] lr-upload-list { + width: min( + calc(var(--uc-dialog-width) - var(--uc-padding) * 2), + calc(var(--uc-dialog-max-width) - var(--uc-padding) * 2), + calc(100vw - var(--uc-padding) * 2) + ); height: max-content; max-height: var(--modal-max-content-height); } lr-upload-list .no-files { - height: var(--ui-size); - padding: var(--gap-max); + height: 32px; + padding: 20px; } lr-upload-list .files { display: block; flex: 1; - min-height: var(--ui-size); - padding: 0 var(--gap-mid); + min-height: 32px; + padding: 0 var(--uc-padding); overflow: auto; } lr-upload-list .toolbar { display: flex; - gap: var(--gap-small); + gap: 4px; justify-content: space-between; - padding: var(--gap-mid); - background-color: var(--clr-background-light); -} - -lr-upload-list .toolbar .add-more-btn { - padding-left: 0.2em; + padding: var(--uc-padding); + background-color: var(--uc-background); } lr-upload-list .toolbar-spacer { @@ -47,24 +47,28 @@ lr-upload-list lr-drop-area { position: absolute; top: 0; left: 0; - width: calc(100% - var(--gap-mid) * 2); - height: calc(100% - var(--gap-mid) * 2); - margin: var(--gap-mid); - border-radius: var(--border-radius-element); + width: calc(100% - var(--uc-padding) * 2); + height: calc(100% - var(--uc-padding) * 2); + margin: var(--uc-padding); + border-radius: var(--uc-radius); } lr-upload-list lr-activity-header > .header-text { - padding: 0 var(--gap-mid); + padding: 0 var(--uc-padding); } lr-upload-list .common-error { - border-radius: var(--border-radius-element); - color: var(--clr-error); - background-color: var(--clr-error-message-bgr); + border-radius: var(--uc-radius); + color: var(--uc-destructive-foreground); + background-color: var(--uc-destructive); display: flex; align-items: center; justify-content: center; - padding: var(--gap-mid); - margin: var(--gap-small) var(--gap-mid) 0 var(--gap-mid); - font-size: 0.95em; + padding: var(--uc-padding); + margin: 4px var(--uc-padding) 0 var(--uc-padding); + font-size: 0.925em; +} + +lr-upload-list .add-more-btn lr-icon { + display: none; } diff --git a/blocks/UrlSource/url-source.css b/blocks/UrlSource/url-source.css index fa3c9ff33..ba3e33b4d 100644 --- a/blocks/UrlSource/url-source.css +++ b/blocks/UrlSource/url-source.css @@ -1,17 +1,21 @@ lr-url-source { display: block; - background-color: var(--clr-background-light); + background-color: var(--uc-background); } -lr-modal lr-url-source { - width: min(calc(var(--modal-normal-w) - var(--gap-mid) * 2), calc(100vw - var(--gap-mid) * 2)); +[lr-modal] lr-url-source { + width: min( + calc(var(--uc-dialog-width) - var(--uc-padding) * 2), + calc(var(--uc-dialog-max-width) - var(--uc-padding) * 2), + calc(100vw - var(--uc-padding) * 2) + ); } lr-url-source > .content { display: grid; - grid-gap: var(--gap-small); + grid-gap: 4px; grid-template-columns: 1fr min-content; - padding: var(--gap-mid); + padding: var(--uc-padding); padding-top: 0; } diff --git a/blocks/Video/Video.js b/blocks/Video/Video.js deleted file mode 100644 index 1168217bf..000000000 --- a/blocks/Video/Video.js +++ /dev/null @@ -1,301 +0,0 @@ -import { Block } from '../../abstract/Block.js'; - -/** @enum {String} */ -const ICO_MAP = { - PLAY: 'play', - PAUSE: 'pause', - FS_ON: 'fullscreen-on', - FS_OFF: 'fullscreen-off', - VOL_ON: 'unmute', - VOL_OFF: 'mute', - CAP_ON: 'captions', - CAP_OFF: 'captions-off', -}; - -// TODO: refactor and move fullscreen adapter to utils: -const FSAPI = { - requestFullscreen: (el) => { - if (el.requestFullscreen) { - el.requestFullscreen(); - } else if (el.webkitRequestFullscreen) { - el.webkitRequestFullscreen(); - } - }, - exitFullscreen: () => { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } - }, -}; - -export class Video extends Block { - togglePlay() { - if (this._video.paused || this._video.ended) { - this._video.play(); - } else { - this._video.pause(); - } - } - - toggleFullscreen() { - if ((document.fullscreenElement || document.webkitFullscreenElement) === this) { - FSAPI.exitFullscreen(); - } else { - FSAPI.requestFullscreen(this); - } - } - - toggleCaptions() { - if (this.$.capIcon === ICO_MAP.CAP_OFF) { - this.$.capIcon = ICO_MAP.CAP_ON; - this._video.textTracks[0].mode = 'showing'; - window.localStorage.setItem(`${Video.is}:captions`, '1'); - } else { - this.$.capIcon = ICO_MAP.CAP_OFF; - this._video.textTracks[0].mode = 'hidden'; - window.localStorage.removeItem(`${Video.is}:captions`); - } - } - - toggleSound() { - if (this.$.volIcon === ICO_MAP.VOL_ON) { - this.$.volIcon = ICO_MAP.VOL_OFF; - this.$.volumeDisabled = true; - this._video.muted = true; - } else { - this.$.volIcon = ICO_MAP.VOL_ON; - this.$.volumeDisabled = false; - this._video.muted = false; - } - } - - setVolume(val) { - window.localStorage.setItem(`${Video.is}:volume`, val); - const volume = val ? val / 100 : 0; - this._video.volume = volume; - } - - /** @type {HTMLElement} */ - get progress() { - return this.ref.progress; - } - - init$ = { - ...this.init$, - src: '', - ppIcon: ICO_MAP.PLAY, - fsIcon: ICO_MAP.FS_ON, - volIcon: ICO_MAP.VOL_ON, - capIcon: ICO_MAP.CAP_OFF, - totalTime: '00:00', - currentTime: '00:00', - progressCssWidth: '0', - hasSubtitles: false, - volumeDisabled: false, - volumeValue: 0, - onPP: () => { - this.togglePlay(); - }, - onFs: () => { - this.toggleFullscreen(); - }, - onCap: () => { - this.toggleCaptions(); - }, - onMute: () => { - this.toggleSound(); - }, - onVolChange: (e) => { - // TODO: cast range.value instead of range.$.value - const val = Number.parseFloat(e.currentTarget.$.value); - this.setVolume(val); - }, - progressClicked: (e) => { - const progressRect = this.progress.getBoundingClientRect(); - this._video.currentTime = this._video.duration * (e.offsetX / progressRect.width); - }, - }; - - /** - * @private - * @param {String} input - */ - _getUrl(input) { - return input.includes('/') ? input : `https://ucarecdn.com/${input}/`; - } - - /** - * @private - * @param {Object} desc - */ - _desc2attrs(desc) { - const attrs = []; - for (const attr in desc) { - const val = attr === 'src' ? this._getUrl(desc[attr]) : desc[attr]; - attrs.push(`${attr}="${val}"`); - } - return attrs.join(' '); - } - - /** - * @private - * @param {Number} seconds - */ - _timeFmt(seconds) { - // TODO: add hours - const date = new Date(Math.round(seconds) * 1000); - return [date.getMinutes(), date.getSeconds()] - .map((n) => { - return n < 10 ? `0${n}` : n; - }) - .join(':'); - } - - /** @private */ - _initTracks() { - for (const track of this._video.textTracks) { - track.mode = 'hidden'; - } - if (window.localStorage.getItem(`${Video.is}:captions`)) { - this.toggleCaptions(); - } - } - - /** @private */ - _castAttributes() { - const toCast = ['autoplay', 'loop', 'muted']; - for (const attr of this.attributes) { - if (toCast.includes(attr.name)) { - this._video.setAttribute(attr.name, attr.value); - } - } - } - - initCallback() { - super.initCallback(); - /** - * @private - * @type {HTMLVideoElement} - */ - this._video = this.ref.video; - - this._castAttributes(); - - this._video.addEventListener('play', () => { - this.$.ppIcon = ICO_MAP.PAUSE; - this.setAttribute('playback', ''); - }); - - this._video.addEventListener('pause', () => { - this.$.ppIcon = ICO_MAP.PLAY; - this.removeAttribute('playback'); - }); - - this.addEventListener('fullscreenchange', (e) => { - console.log(e); - if (document.fullscreenElement === this) { - this.$.fsIcon = ICO_MAP.FS_OFF; - } else { - this.$.fsIcon = ICO_MAP.FS_ON; - } - }); - - this.sub('src', (src) => { - if (!src) { - return; - } - const url = this._getUrl(src); - this._video.src = url; - }); - - this.sub('video', async (descPath) => { - if (!descPath) { - return; - } - const desc = await (await window.fetch(this._getUrl(descPath))).json(); - - if (desc.poster) { - this._video.poster = this._getUrl(desc.poster); - } - - let html = ''; - if (desc.sources) { - for (const srcDesc of desc.sources) { - html += /* HTML */ ``; - } - } - - if (desc.tracks) { - for (const trackDesc of desc.tracks) { - html += /* HTML */ ``; - } - this.$.hasSubtitles = true; - } - - this._video.innerHTML += html; - - this._initTracks(); - console.log(desc); - }); - - this._video.addEventListener('loadedmetadata', (e) => { - this.$.currentTime = this._timeFmt(this._video.currentTime); - this.$.totalTime = this._timeFmt(this._video.duration); - }); - - this._video.addEventListener('timeupdate', (e) => { - const perc = Math.round(100 * (this._video.currentTime / this._video.duration)); - this.$.progressCssWidth = `${perc}%`; - this.$.currentTime = this._timeFmt(this._video.currentTime); - }); - - const volume = window.localStorage.getItem(`${Video.is}:volume`); - if (volume) { - const vol = Number.parseFloat(volume); - this.setVolume(vol); - this.$.volumeValue = vol; - } - } -} - -Video.template = /* HTML */ ` - - - - - - - - - - - - - - {{currentTime}} / {{totalTime}} - - - - - - - - - - - - - - - - - - -`; - -Video.bindAttributes({ - video: 'video', - src: 'src', -}); diff --git a/blocks/Video/test-track.vtt b/blocks/Video/test-track.vtt deleted file mode 100644 index 1141e5b6a..000000000 --- a/blocks/Video/test-track.vtt +++ /dev/null @@ -1,10 +0,0 @@ -WEBVTT - -00:01.000 --> 00:04.000 -- Hello lr-video! - -00:05.000 --> 00:15.000 -- This is subtitles test. - -00:16.000 --> 00:30.000 -- Try to turn off and then turn on subtitles... \ No newline at end of file diff --git a/blocks/Video/video.css b/blocks/Video/video.css deleted file mode 100644 index 85499ee3c..000000000 --- a/blocks/Video/video.css +++ /dev/null @@ -1,106 +0,0 @@ -@import url('../Range/range.css'); - -lr-video { - --color-accent: rgb(196, 243, 255); - - display: inline-grid; - grid-template-rows: 1fr min-content; - max-height: var(--uploadcare-blocks-window-height, 100vh); - overflow: hidden; - font-family: monospace; - background-color: #000; - border-radius: 6px; -} - -lr-video [hidden] { - display: none !important; -} - -lr-video lr-range[disabled] { - opacity: 0.4; - pointer-events: none; -} - -lr-video .video-wrapper { - overflow: hidden; -} - -lr-video video { - display: inline-block; - width: 100%; - max-width: 100%; - height: 100%; - margin: 0; - padding: 0; - background-color: #ccc; - background-color: #000; -} - -lr-video lr-icon { - --icon-play: 'M8,5.14V19.14L19,12.14L8,5.14Z'; - --icon-pause: 'M14,19H18V5H14M6,19H10V5H6V19Z'; - --icon-mute: 'M12,4L9.91,6.09L12,8.18M4.27,3L3,4.27L7.73,9H3V15H7L12,20V13.27L16.25,17.53C15.58,18.04 14.83,18.46 14,18.7V20.77C15.38,20.45 16.63,19.82 17.68,18.96L19.73,21L21,19.73L12,10.73M19,12C19,12.94 18.8,13.82 18.46,14.64L19.97,16.15C20.62,14.91 21,13.5 21,12C21,7.72 18,4.14 14,3.23V5.29C16.89,6.15 19,8.83 19,12M16.5,12C16.5,10.23 15.5,8.71 14,7.97V10.18L16.45,12.63C16.5,12.43 16.5,12.21 16.5,12Z'; - --icon-unmute: 'M14,3.23V5.29C16.89,6.15 19,8.83 19,12C19,15.17 16.89,17.84 14,18.7V20.77C18,19.86 21,16.28 21,12C21,7.72 18,4.14 14,3.23M16.5,12C16.5,10.23 15.5,8.71 14,7.97V16C15.5,15.29 16.5,13.76 16.5,12M3,9V15H7L12,20V4L7,9H3Z'; - --icon-fullscreen-on: 'M5,5H10V7H7V10H5V5M14,5H19V10H17V7H14V5M17,14H19V19H14V17H17V14M10,17V19H5V14H7V17H10Z'; - --icon-fullscreen-off: 'M14,14H19V16H16V19H14V14M5,14H10V19H8V16H5V14M8,5H10V10H5V8H8V5M19,8V10H14V5H16V8H19Z'; - --icon-captions: 'M18,11H16.5V10.5H14.5V13.5H16.5V13H18V14A1,1 0 0,1 17,15H14A1,1 0 0,1 13,14V10A1,1 0 0,1 14,9H17A1,1 0 0,1 18,10M11,11H9.5V10.5H7.5V13.5H9.5V13H11V14A1,1 0 0,1 10,15H7A1,1 0 0,1 6,14V10A1,1 0 0,1 7,9H10A1,1 0 0,1 11,10M19,4H5C3.89,4 3,4.89 3,6V18A2,2 0 0,0 5,20H19A2,2 0 0,0 21,18V6C21,4.89 20.1,4 19,4Z'; - --icon-captions-off: 'M5,4C4.45,4 4,4.18 3.59,4.57C3.2,4.96 3,5.44 3,6V18C3,18.56 3.2,19.04 3.59,19.43C4,19.82 4.45,20 5,20H19C19.5,20 20,19.81 20.39,19.41C20.8,19 21,18.53 21,18V6C21,5.47 20.8,5 20.39,4.59C20,4.19 19.5,4 19,4H5M4.5,5.5H19.5V18.5H4.5V5.5M7,9C6.7,9 6.47,9.09 6.28,9.28C6.09,9.47 6,9.7 6,10V14C6,14.3 6.09,14.53 6.28,14.72C6.47,14.91 6.7,15 7,15H10C10.27,15 10.5,14.91 10.71,14.72C10.91,14.53 11,14.3 11,14V13H9.5V13.5H7.5V10.5H9.5V11H11V10C11,9.7 10.91,9.47 10.71,9.28C10.5,9.09 10.27,9 10,9H7M14,9C13.73,9 13.5,9.09 13.29,9.28C13.09,9.47 13,9.7 13,10V14C13,14.3 13.09,14.53 13.29,14.72C13.5,14.91 13.73,15 14,15H17C17.3,15 17.53,14.91 17.72,14.72C17.91,14.53 18,14.3 18,14V13H16.5V13.5H14.5V10.5H16.5V11H18V10C18,9.7 17.91,9.47 17.72,9.28C17.53,9.09 17.3,9 17,9H14Z'; - - display: inline-flex; - align-items: center; - justify-content: center; - fill: currentColor; -} - -lr-video:not([controls]) .toolbar { - display: none; -} - -lr-video .toolbar { - position: relative; - z-index: 10000; - display: flex; - align-items: center; - justify-content: space-between; - color: var(--color-accent); - background-color: #000; - transition: 0.4s; -} -lr-video[playback] .toolbar { - opacity: 0.2; -} -lr-video .toolbar:hover { - opacity: 1; -} - -lr-video .toolbar .tb-block { - display: flex; - align-items: center; -} - -lr-video .toolbar .tb-block button { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 40px; - height: 40px; - color: var(--color-accent); - background-color: transparent; - border: none; - cursor: pointer; -} -lr-video .progress { - position: absolute; - top: -18px; - right: 0; - left: 0; - display: flex; - align-items: flex-end; - height: 20px; - cursor: pointer; -} -lr-video .progress .bar { - height: 2px; - background-color: var(--color-accent); - transition: 0.5s; -} diff --git a/blocks/Video/video.json b/blocks/Video/video.json deleted file mode 100644 index 180578666..000000000 --- a/blocks/Video/video.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "sources": [ - { - "label": "HQ", - "src": "d52902bb-c7d3-4e00-9f80-ed489dda9a3f", - "type": "video/mp4" - }, - { - "label": "MQ", - "src": "d52902bb-c7d3-4e00-9f80-ed489dda9a3f", - "type": "video/mp4" - }, - { - "label": "LQ", - "src": "d52902bb-c7d3-4e00-9f80-ed489dda9a3f", - "type": "video/mp4" - } - ], - "tracks": [ - { - "kind": "subtitles", - "src": "bd8fd88a-a2ea-49a7-825b-4a68c355667c", - "srclang": "en", - "label": "EN", - "default": true - } - ], - "poster": "89409d82-8939-4c6f-8410-d4b6bcb404d9" -} diff --git a/blocks/svg-backgrounds/svg-backgrounds.js b/blocks/svg-backgrounds/svg-backgrounds.js index ec4aa7477..9f04c22ef 100644 --- a/blocks/svg-backgrounds/svg-backgrounds.js +++ b/blocks/svg-backgrounds/svg-backgrounds.js @@ -39,7 +39,7 @@ export function strokesCssBg(color = 'rgba(0, 0, 0, .1)') { export function fileCssBg(color = 'hsl(209, 21%, 65%)', width = 32, height = 32) { return createSvgBlobUrl(/*svg*/ ` - + `); } diff --git a/blocks/themes/lr-basic/README.md b/blocks/themes/lr-basic/README.md deleted file mode 100644 index 81b41591f..000000000 --- a/blocks/themes/lr-basic/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Basic theme for blocks - -There are 4 levels of abstraction: - -- [Base values](#base-values) -- [Derivative values](#derivative-values]) -- [Common styles](#common-styles) -- [Component styles](#component-styles) - -### HSL color space - -We use HSL color space because it allows us to easily calculate derivative colors. That's what prefixes `--h-`, `--s-`, and `--l-` are stand for. - -### Quick styling - -In most cases switching the dark mode on or off and changing the accent color is enough to make blocks match your design. - - - -```css ---darkmode: 1; -``` - -```css ---h-accent: 211; ---s-accent: 100%; ---l-accent: calc(50% - 5% * var(--darkmode)); -``` - -## Base values - -- `--darkmode` — `1`: dark mode enabled, `0`: disabled; -- `--*-foreground` — text color, borders, and shaders. It should be in contrast to the background; -- `--*-background` — background color and its variations; -- `--*-accent` — colors of buttons, links, and text input borders (hover and focus). It should be in contrast to the background; -- `--*-confirm` — the color of confirmation notifications and badges; -- `--*-error` — the color of error notifications and badges; -- `--opacity-*` — opacity of different states of small icon buttons; -- `--ui-size` — minimum size of a clickable element. Also used to calculate the size of the elements, which should be proportional to it; -- `--gap-*` — paddings and margins; -- `--gap-table` — the gap between elements in lists (for example, in upload-list); -- `--borders` — `1`: borders enabled, `0`: disabled. Can be fractional, for example, 0.5 will make borders half as opaque; -- `--border-radius-element` — border radius of buttons and inputs; -- `--border-radius-frame` — border radius of modal windows and drop area; -- `--border-radius-thumb` — border radius of thumbnails; -- `--transition-duration` — duration of all animated transitions; -- `--shadows` — `1`: shadows enabled, `0`: disabled. Can be fractional, for example 0.5, will make shadows half as opaque; -- `--*-shadow` — the color of box shadows; -- `--modal-max-w`, `--modal-max-h` — the maximum size of the modal window. - -## Derivative values - -Derivative values are calculated from the base values. - -- `--darkmode-minus` — used for dark mode color calculations. Gives `-1` when dark mode is enabled, `1` when disabled; -- `--clr-background*` — lightness variations of the background color; -- `--clr-accent*` — opacity variations of the accent color; -- `--clr-confirm` — confirmation notifications color; -- `--clr-error` — opacity and lighness variations of the error notifications color; -- `--clr-txt*` — lightness variations of the text color; -- `--clr-shade-lv*` — shading colors (foreground color with a low opacity variations); -- `--border-*` — border variations; -- `--clr-curtain` — color of the background behind the modal window; -- `--clr-btn-bgr-primary*`, `--clr-btn-txt-primary`, `--shadow-btn-primary` — primary action button values; -- `--clr-btn-bgr-secondary*`, `--clr-btn-txt-secondary`, `--shadow-btn-secondary` — secondary action button values; -- `--clr-btn-bgr-disabled`, `--clr-btn-txt-disabled`, `--shadow-btn-disabled` — disabled button values. - -## Common styles - -Common styles define similar UI elements across different blocks: buttons, inputs, and links. - -## Component styles - -Component styles are the most specific. - - diff --git a/blocks/themes/lr-basic/common.css b/blocks/themes/lr-basic/common.css index a9ec63f5f..748d2d343 100644 --- a/blocks/themes/lr-basic/common.css +++ b/blocks/themes/lr-basic/common.css @@ -1,167 +1,116 @@ -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) { - color: var(--clr-txt); - - /* font-size and family for testing purposes, to be removed */ - font-size: 14px; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', - 'Helvetica Neue', sans-serif; +:where([lr-wgt-common]) { + color: var(--uc-foreground); + font-size: var(--uc-font-size); + line-height: var(--uc-line-height); + font-family: var(--uc-font-family); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) * { +:where([lr-wgt-common]) * { box-sizing: border-box; } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - [hidden] { +:where([lr-wgt-common]) [hidden] { display: none !important; } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - [activity]:not([active]) { +:where([lr-wgt-common]) [activity]:not([active]) { display: none; } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - dialog:not([open]) - [activity] { +:where([lr-wgt-common]) dialog:not([open]) [activity] { display: none; } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button { +:where([lr-wgt-common]) button { display: flex; align-items: center; justify-content: center; - height: var(--ui-size); - padding-right: 1.4em; - padding-left: 1.4em; + height: var(--uc-button-size); + padding-right: 14px; + padding-left: 14px; font-size: 1em; font-family: inherit; white-space: nowrap; border: none; - border-radius: var(--border-radius-element); + border-radius: var(--uc-radius); cursor: pointer; user-select: none; + transition: background-color var(--uc-transition); } -@media only screen and (max-width: 800px) { - :where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button { - padding-right: 1em; - padding-left: 1em; - } -} - -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.primary-btn { - color: var(--clr-btn-txt-primary); - background-color: var(--clr-btn-bgr-primary); - box-shadow: var(--shadow-btn-primary); - transition: background-color var(--transition-duration); -} - -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.primary-btn:hover { - background-color: var(--clr-btn-bgr-primary-hover); -} - -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.primary-btn:active { - background-color: var(--clr-btn-bgr-primary-active); +:where([lr-wgt-common]) button.primary-btn { + color: var(--uc-primary-foreground); + background-color: var(--uc-primary); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.secondary-btn { - color: var(--clr-btn-txt-secondary); - background-color: var(--clr-btn-bgr-secondary); - box-shadow: var(--shadow-btn-secondary); - transition: background-color var(--transition-duration); +:where([lr-wgt-common]) button.primary-btn:hover { + background-color: var(--uc-primary-hover); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.secondary-btn:hover { - background-color: var(--clr-btn-bgr-secondary-hover); +:where([lr-wgt-common]) button.secondary-btn { + color: var(--uc-secondary-foreground); + background-color: var(--uc-secondary); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.secondary-btn:active { - background-color: var(--clr-btn-bgr-secondary-active); +:where([lr-wgt-common]) button.secondary-btn:hover { + background-color: var(--uc-secondary-hover); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.mini-btn { - width: var(--ui-size); - height: var(--ui-size); +:where([lr-wgt-common]) button.mini-btn { + height: var(--uc-button-size); padding: 0; background-color: transparent; - border: none; - cursor: pointer; - transition: var(--transition-duration) ease; - color: var(--clr-txt); -} - -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.mini-btn:hover { - background-color: var(--clr-shade-lv1); + color: var(--uc-secondary-foreground); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - button.mini-btn:active { - background-color: var(--clr-shade-lv2); +:where([lr-wgt-common]) button.mini-btn:hover { + background-color: var(--uc-secondary); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - :is(button[disabled], button.primary-btn[disabled], button.secondary-btn[disabled]) { - color: var(--clr-btn-txt-disabled); - background-color: var(--clr-btn-bgr-disabled); - box-shadow: var(--shadow-btn-disabled); +:where([lr-wgt-common]) :is(button[disabled], button.primary-btn[disabled], button.secondary-btn[disabled]) { + opacity: 0.5; pointer-events: none; } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) a { - color: var(--clr-accent); +:where([lr-wgt-common]) a { + color: var(--uc-primary); text-decoration: none; } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - a[disabled] { +/* TODO: if we're using disabled somewhere, we should stop */ +:where([lr-wgt-common]) a[disabled] { pointer-events: none; } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - input[type='text'] { +:where([lr-wgt-common]) input[type='text'] { display: flex; width: 100%; - height: var(--ui-size); - padding-right: 0.6em; - padding-left: 0.6em; - color: var(--clr-txt); + height: var(--uc-button-size); + padding-right: 10px; + padding-left: 10px; + color: var(--uc-foreground); font-size: 1em; font-family: inherit; - background-color: var(--clr-background-light); - border: var(--border-light); - border-radius: var(--border-radius-element); - transition: var(--transition-duration); -} - -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - input[type='text']::placeholder { - color: var(--clr-txt-lightest); + background-color: var(--uc-background); + border: 1px solid var(--uc-border); + outline: 1px solid transparent; + border-radius: var(--uc-radius); + transition: + border-color var(--uc-transition), + outline-color var(--uc-transition); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - input[type='text']:hover { - border-color: var(--clr-accent-light); +:where([lr-wgt-common]) input[type='text']::placeholder { + color: var(--uc-muted-foreground); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - input[type='text']:focus { - border-color: var(--clr-accent); - outline: none; +:where([lr-wgt-common]) input[type='text']:focus { + outline-color: var(--uc-primary-hover); + border-color: var(--uc-primary-hover); } -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) - input[disabled] { +/* TODO: check if there's any necessity of disabled input */ +:where([lr-wgt-common]) input[disabled] { opacity: 0.6; pointer-events: none; } diff --git a/blocks/themes/lr-basic/config.css b/blocks/themes/lr-basic/config.css index 36e30bc6e..06b54affb 100644 --- a/blocks/themes/lr-basic/config.css +++ b/blocks/themes/lr-basic/config.css @@ -1,47 +1,4 @@ -:where(.lr-wgt-cfg, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) { - --cfg-pubkey: 'YOUR_PUBLIC_KEY'; - --cfg-multiple: 1; - --cfg-multiple-min: 0; - --cfg-multiple-max: 0; - - --cfg-confirm-upload: 0; - --cfg-img-only: 0; - --cfg-accept: ''; - --cfg-external-sources-preferred-types: ''; - --cfg-store: 'auto'; - --cfg-camera-mirror: 1; - --cfg-source-list: 'local, url, camera, dropbox, gdrive'; - --cfg-max-local-file-size-bytes: 0; - --cfg-thumb-size: 76; - --cfg-show-empty-list: 0; - --cfg-use-local-image-editor: 0; - --cfg-use-cloud-image-editor: 1; - --cfg-remove-copyright: 0; - - --cfg-modal-scroll-lock: 1; - --cfg-modal-backdrop-strokes: 0; - - --cfg-source-list-wrap: 1; - +:where([lr-wgt-common]) { --cfg-init-activity: 'start-from'; --cfg-done-activity: ''; - - --cfg-remote-tab-session-key: ''; - --cfg-cdn-cname: 'https://ucarecdn.com'; - --cfg-base-url: 'https://upload.uploadcare.com'; - --cfg-social-base-url: 'https://social.uploadcare.com'; - --cfg-secure-signature: ''; - --cfg-secure-expire: ''; - --cfg-secure-delivery-proxy: ''; - --cfg-retry-throttled-request-max-times: 1; - --cfg-multipart-min-file-size: 26214400; /* 25MB */ - --cfg-multipart-chunk-size: 5242880; /* 5MB */ - --cfg-max-concurrent-requests: 10; - --cfg-multipart-max-concurrent-requests: 4; - --cfg-multipart-max-attempts: 3; - --cfg-check-for-url-duplicates: 0; - --cfg-save-url-for-recurrent-uploads: 0; - - --cfg-group-output: 0; - --cfg-user-agent-integration: ''; } diff --git a/blocks/themes/lr-basic/icons/check.svg b/blocks/themes/lr-basic/icons/check.svg deleted file mode 100644 index c09d48bb7..000000000 --- a/blocks/themes/lr-basic/icons/check.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/detail.svg b/blocks/themes/lr-basic/icons/detail.svg deleted file mode 100644 index 55759bca2..000000000 --- a/blocks/themes/lr-basic/icons/detail.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/dots.svg b/blocks/themes/lr-basic/icons/dots.svg deleted file mode 100644 index f5b2f365e..000000000 --- a/blocks/themes/lr-basic/icons/dots.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-brightness.svg b/blocks/themes/lr-basic/icons/edit-brightness.svg deleted file mode 100644 index dde83dd28..000000000 --- a/blocks/themes/lr-basic/icons/edit-brightness.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-color.svg b/blocks/themes/lr-basic/icons/edit-color.svg deleted file mode 100644 index 72ba8de67..000000000 --- a/blocks/themes/lr-basic/icons/edit-color.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-contrast.svg b/blocks/themes/lr-basic/icons/edit-contrast.svg deleted file mode 100644 index af76cee71..000000000 --- a/blocks/themes/lr-basic/icons/edit-contrast.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-crop.svg b/blocks/themes/lr-basic/icons/edit-crop.svg deleted file mode 100644 index 64e3c5b4d..000000000 --- a/blocks/themes/lr-basic/icons/edit-crop.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-draw.svg b/blocks/themes/lr-basic/icons/edit-draw.svg deleted file mode 100644 index fe1d72141..000000000 --- a/blocks/themes/lr-basic/icons/edit-draw.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-file.svg b/blocks/themes/lr-basic/icons/edit-file.svg deleted file mode 100644 index 9188f9785..000000000 --- a/blocks/themes/lr-basic/icons/edit-file.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-flip-h.svg b/blocks/themes/lr-basic/icons/edit-flip-h.svg deleted file mode 100644 index f44f858ad..000000000 --- a/blocks/themes/lr-basic/icons/edit-flip-h.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-flip-v.svg b/blocks/themes/lr-basic/icons/edit-flip-v.svg deleted file mode 100644 index b1794aa6b..000000000 --- a/blocks/themes/lr-basic/icons/edit-flip-v.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-guides.svg b/blocks/themes/lr-basic/icons/edit-guides.svg deleted file mode 100644 index 8b392fc93..000000000 --- a/blocks/themes/lr-basic/icons/edit-guides.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-resize.svg b/blocks/themes/lr-basic/icons/edit-resize.svg deleted file mode 100644 index 759ccc880..000000000 --- a/blocks/themes/lr-basic/icons/edit-resize.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-rotate.svg b/blocks/themes/lr-basic/icons/edit-rotate.svg deleted file mode 100644 index be7ac2f30..000000000 --- a/blocks/themes/lr-basic/icons/edit-rotate.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-saturation.svg b/blocks/themes/lr-basic/icons/edit-saturation.svg deleted file mode 100644 index 3b26e45ef..000000000 --- a/blocks/themes/lr-basic/icons/edit-saturation.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit-text.svg b/blocks/themes/lr-basic/icons/edit-text.svg deleted file mode 100644 index 7f351d4f0..000000000 --- a/blocks/themes/lr-basic/icons/edit-text.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/edit.svg b/blocks/themes/lr-basic/icons/edit.svg deleted file mode 100644 index 5dc4b2ebf..000000000 --- a/blocks/themes/lr-basic/icons/edit.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/fullscreen-exit.svg b/blocks/themes/lr-basic/icons/fullscreen-exit.svg deleted file mode 100644 index b6003ee18..000000000 --- a/blocks/themes/lr-basic/icons/fullscreen-exit.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/fullscreen.svg b/blocks/themes/lr-basic/icons/fullscreen.svg deleted file mode 100644 index 09d822573..000000000 --- a/blocks/themes/lr-basic/icons/fullscreen.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/remove.svg b/blocks/themes/lr-basic/icons/remove.svg deleted file mode 100644 index d21bfd88e..000000000 --- a/blocks/themes/lr-basic/icons/remove.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/icons/trash-file.svg b/blocks/themes/lr-basic/icons/trash-file.svg deleted file mode 100644 index d21bfd88e..000000000 --- a/blocks/themes/lr-basic/icons/trash-file.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/blocks/themes/lr-basic/index.css b/blocks/themes/lr-basic/index.css index 91190d231..a6c16b8ec 100644 --- a/blocks/themes/lr-basic/index.css +++ b/blocks/themes/lr-basic/index.css @@ -9,9 +9,7 @@ /* UI COMPONENTS: */ @import url('../../Icon/icon.css'); -@import url('../../Tabs/tabs.css'); @import url('../../Range/range.css'); -@import url('../../Color/color.css'); /* BLOCKS: */ @import url('../../Config/config.css'); @@ -25,10 +23,6 @@ @import url('../../UploadList/upload-list.css'); @import url('../../StartFrom/start-from.css'); @import url('../../FileItem/file-item.css'); - -/* @import url('../../EditableCanvas/editable-canvas.css'); */ -@import url('../../FilePreview/file-preview.css'); -@import url('../../ConfirmationDialog/confirmation.css'); @import url('../../ProgressBarCommon/progress-bar-common.css'); @import url('../../ProgressBar/progress-bar.css'); @import url('../../ActivityHeader/activity-header.css'); diff --git a/blocks/themes/lr-basic/svg-sprite.js b/blocks/themes/lr-basic/svg-sprite.js index 2171ed888..c5906653f 100644 --- a/blocks/themes/lr-basic/svg-sprite.js +++ b/blocks/themes/lr-basic/svg-sprite.js @@ -1 +1 @@ -export default ""; +export default ""; \ No newline at end of file diff --git a/blocks/themes/lr-basic/theme.css b/blocks/themes/lr-basic/theme.css index fc711339c..0673d3ad4 100644 --- a/blocks/themes/lr-basic/theme.css +++ b/blocks/themes/lr-basic/theme.css @@ -1,181 +1,232 @@ -:where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) { - /* Base values */ - - --darkmode: 0; - - --h-foreground: 208; - --s-foreground: 4%; - --l-foreground: calc(10% + 78% * var(--darkmode)); - - --h-background: 208; - --s-background: 4%; - --l-background: calc(97% - 85% * var(--darkmode)); - - --h-accent: 211; - --s-accent: 100%; - --l-accent: calc(50% - 5% * var(--darkmode)); - - --h-confirm: 137; - --s-confirm: 85%; - --l-confirm: 53%; - - --h-error: 358; - --s-error: 100%; - --l-error: 66%; - - --shadows: 1; - - --h-shadow: 0; - --s-shadow: 0%; - --l-shadow: 0%; - - --opacity-normal: 0.6; - --opacity-hover: 0.9; - --opacity-active: 1; - - --ui-size: 32px; - - --gap-min: 2px; - --gap-small: 4px; - --gap-mid: 10px; - --gap-max: 20px; - --gap-table: 0px; - - --borders: 1; - - --border-radius-element: 8px; - --border-radius-frame: 12px; - --border-radius-thumb: 6px; - - --transition-duration: 0.2s; - - --modal-max-w: 800px; - --modal-max-h: 600px; - --modal-normal-w: 430px; - - /* Derivative values */ - - --darkmode-minus: calc(1 + var(--darkmode) * -2); - - --clr-background: hsl(var(--h-background), var(--s-background), var(--l-background)); - --clr-background-dark: hsl( - var(--h-background), - var(--s-background), - calc(var(--l-background) - 3% * var(--darkmode-minus)) - ); - --clr-background-light: hsl( - var(--h-background), - var(--s-background), - calc(var(--l-background) + 3% * var(--darkmode-minus)) - ); - - --clr-accent: hsl(var(--h-accent), var(--s-accent), calc(var(--l-accent) + 15% * var(--darkmode))); - --clr-accent-light: hsla(var(--h-accent), var(--s-accent), var(--l-accent), 30%); - --clr-accent-lightest: hsla(var(--h-accent), var(--s-accent), var(--l-accent), 10%); - --clr-accent-light-opaque: hsl(var(--h-accent), var(--s-accent), calc(var(--l-accent) + 45% * var(--darkmode-minus))); - --clr-accent-lightest-opaque: hsl( - var(--h-accent), - var(--s-accent), - calc(var(--l-accent) + 47% * var(--darkmode-minus)) - ); - - --clr-confirm: hsl(var(--h-confirm), var(--s-confirm), var(--l-confirm)); - - --clr-error: hsl(var(--h-error), var(--s-error), var(--l-error)); - --clr-error-light: hsla(var(--h-error), var(--s-error), var(--l-error), 15%); - --clr-error-lightest: hsla(var(--h-error), var(--s-error), var(--l-error), 5%); - --clr-error-message-bgr: hsl(var(--h-error), var(--s-error), calc(var(--l-error) + 31% * var(--darkmode-minus))); - - --clr-txt: hsl(var(--h-foreground), var(--s-foreground), var(--l-foreground)); - --clr-txt-mid: hsl(var(--h-foreground), var(--s-foreground), calc(var(--l-foreground) + 20% * var(--darkmode-minus))); - --clr-txt-light: hsl( - var(--h-foreground), - var(--s-foreground), - calc(var(--l-foreground) + 30% * var(--darkmode-minus)) - ); - --clr-txt-lightest: hsl( - var(--h-foreground), - var(--s-foreground), - calc(var(--l-foreground) + 50% * var(--darkmode-minus)) - ); - - --clr-shade-lv1: hsla(var(--h-foreground), var(--s-foreground), var(--l-foreground), 5%); - --clr-shade-lv2: hsla(var(--h-foreground), var(--s-foreground), var(--l-foreground), 8%); - --clr-shade-lv3: hsla(var(--h-foreground), var(--s-foreground), var(--l-foreground), 12%); - - --clr-generic-file-icon: var(--clr-txt-lightest); - - --border-light: 1px solid - hsla( - var(--h-foreground), - var(--s-foreground), - var(--l-foreground), - calc((0.1 - 0.05 * var(--darkmode)) * var(--borders)) - ); - --border-mid: 1px solid - hsla( - var(--h-foreground), - var(--s-foreground), - var(--l-foreground), - calc((0.2 - 0.1 * var(--darkmode)) * var(--borders)) - ); - --border-accent: 1px solid hsla(var(--h-accent), var(--s-accent), var(--l-accent), 1 * var(--borders)); - --border-dashed: 1px dashed - hsla(var(--h-foreground), var(--s-foreground), var(--l-foreground), calc(0.2 * var(--borders))); - - --clr-curtain: hsla(var(--h-background), var(--s-background), calc(var(--l-background)), 60%); - - --hsl-shadow: var(--h-shadow), var(--s-shadow), var(--l-shadow); - - --modal-shadow: 0px 0px 1px hsla(var(--hsl-shadow), calc((0.3 + 0.65 * var(--darkmode)) * var(--shadows))), - 0px 6px 20px hsla(var(--hsl-shadow), calc((0.1 + 0.4 * var(--darkmode)) * var(--shadows))); - - --clr-btn-bgr-primary: var(--clr-accent); - --clr-btn-bgr-primary-hover: hsl( - var(--h-accent), - var(--s-accent), - calc(var(--l-accent) - 4% * var(--darkmode-minus)) - ); - --clr-btn-bgr-primary-active: hsl( - var(--h-accent), - var(--s-accent), - calc(var(--l-accent) - 8% * var(--darkmode-minus)) - ); - --clr-btn-txt-primary: hsl(var(--h-accent), var(--s-accent), 98%); - --shadow-btn-primary: none; +:where([lr-wgt-common]) { + /* Font */ + --uc-font-family: system-ui; + --uc-font-size: 14px; + --uc-line-height: normal; + --uc-simple-btn-font-family: system-ui; + --uc-simple-btn-font-size: 14px; + + /* Sizes */ + --uc-button-size: 32px; + --uc-preview-size: 32px; + --uc-padding: 10px; + --uc-radius: 8px; + --uc-transition: 0.2s ease; + --uc-dialog-width: 430px; + --uc-dialog-max-width: 800px; + --uc-dialog-max-height: 600px; + --uc-simple-btn-padding: 7px 14px; + + /* Default colors, in case of media query failure */ + --uc-background: var(--uc-background-light); + --uc-foreground: var(--uc-foreground-light); + --uc-primary: var(--uc-primary-light); + --uc-primary-hover: var(--uc-primary-hover-light); + --uc-primary-transparent: var(--uc-primary-transparent-light); + --uc-primary-foreground: var(--uc-primary-foreground-light); + --uc-secondary: var(--uc-secondary-light); + --uc-secondary-hover: var(--uc-secondary-hover-light); + --uc-secondary-foreground: var(--uc-secondary-foreground-light); + --uc-muted: var(--uc-muted-light); + --uc-muted-foreground: var(--uc-muted-foreground-light); + --uc-destructive: var(--uc-destructive-light); + --uc-destructive-foreground: var(--uc-destructive-foreground-light); + --uc-border: var(--uc-border-light); + --uc-dialog-shadow: var(--uc-dialog-shadow-light); + --uc-simple-btn: var(--uc-simple-btn-light); + --uc-simple-btn-hover: var(--uc-simple-btn-hover-light); + --uc-simple-btn-foreground: var(--uc-simple-btn-foreground-light); +} - --clr-btn-bgr-secondary: hsl( - var(--h-background), - var(--s-background), - calc(var(--l-background) - 3% * var(--darkmode-minus)) - ); - --clr-btn-bgr-secondary-hover: hsl( - var(--h-background), - var(--s-background), - calc(var(--l-background) - 7% * var(--darkmode-minus)) - ); - --clr-btn-bgr-secondary-active: hsl( - var(--h-background), - var(--s-background), - calc(var(--l-background) - 12% * var(--darkmode-minus)) - ); - --clr-btn-txt-secondary: var(--clr-txt-mid); - --shadow-btn-secondary: none; +@supports not (color: oklch(0% 0 0)) { + :where([lr-wgt-common]) { + /* Light colors RGB fallback */ + --uc-primary-rgb-light: 54 112 253; + --uc-primary-light: rgb(var(--uc-primary-rgb-light)); + --uc-primary-hover-light: rgb(var(--uc-primary-rgb-light) / 90%); + --uc-primary-transparent-light: rgb(var(--uc-primary-rgb-light) / 10%); + --uc-background-light: rgb(255 255 255); + --uc-foreground-light: rgb(24 24 24); + --uc-primary-foreground-light: #fff; + --uc-secondary-light: rgb(24 24 24 / 5%); + --uc-secondary-hover-light: rgb(24 24 24 / 8%); + --uc-secondary-foreground-light: rgb(24 24 24); + --uc-muted-light: rgb(245 245 245); + --uc-muted-foreground-light: rgb(113 113 113); + --uc-destructive-light: rgb(232 19 20 / 5%); + --uc-destructive-foreground-light: rgb(232 19 20); + --uc-border-light: rgb(228 228 232); + --uc-dialog-shadow-light: 0px 6px 20px rgb(0 0 0 / 10%); + --uc-simple-btn-light: rgb(235 235 235); + --uc-simple-btn-hover-light: rgb(228 228 228); + --uc-simple-btn-foreground-light: rgb(24 24 24); + + /* Dark colors RGB fallback */ + --uc-primary-rgb-dark: 87 154 255; + --uc-primary-dark: rgb(var(--uc-primary-rgb-dark)); + --uc-primary-hover-dark: rgb(var(--uc-primary-rgb-dark) / 90%); + --uc-primary-transparent-dark: rgb(var(--uc-primary-rgb-dark) / 7%); + --uc-background-dark: rgb(27 27 27); + --uc-foreground-dark: rgb(225 225 225); + --uc-primary-foreground-dark: rgb(0 0 0); + --uc-secondary-dark: rgb(225 225 225 / 7%); + --uc-secondary-hover-dark: rgb(225 225 225 / 10%); + --uc-secondary-foreground-dark: rgb(225 225 225); + --uc-muted-dark: rgb(36 36 36); + --uc-muted-foreground-dark: rgb(152 152 152); + --uc-destructive-dark: rgb(244 90 79 / 10%); + --uc-destructive-foreground-dark: rgb(244 90 79); + --uc-border-dark: rgb(61 61 61); + --uc-dialog-shadow-dark: 0px 6px 20px rgb(0 0 0 / 25%); + --uc-simple-btn-dark: rgb(36 36 36); + --uc-simple-btn-hover-dark: rgb(43 43 43); + --uc-simple-btn-foreground-dark: rgb(255 255 255); + } +} - --clr-btn-bgr-disabled: var(--clr-background); - --clr-btn-txt-disabled: var(--clr-txt-lightest); - --shadow-btn-disabled: none; +@supports (color: oklch(0% 0 0)) { + :where([lr-wgt-common]) { + /* Light colors OKLCH */ + --uc-primary-oklch-light: 59% 0.22 264; /* Quick customization: change this value to your brand color */ + --uc-primary-light: oklch(var(--uc-primary-oklch-light)); + --uc-primary-hover-light: oklch(var(--uc-primary-oklch-light) / 90%); + --uc-primary-transparent-light: oklch(var(--uc-primary-oklch-light) / 10%); + --uc-background-light: oklch(100% 0 0); + --uc-foreground-light: oklch(21% 0 0); + --uc-primary-foreground-light: oklch(100% 0 0); + --uc-secondary-light: oklch(21% 0 0 / 0.05); + --uc-secondary-hover-light: oklch(21% 0 0 / 0.08); + --uc-secondary-foreground-light: oklch(21% 0 0); + --uc-muted-light: oklch(97% 0 0); + --uc-muted-foreground-light: oklch(55% 0 0); + --uc-destructive-light: oklch(59% 0.235 28.5 / 0.05); + --uc-destructive-foreground-light: oklch(59% 0.235 28.5); + --uc-border-light: oklch(92% 0 0); + --uc-dialog-shadow-light: 0px 6px 20px oklch(0% 0 0 / 0.1); + --uc-simple-btn-light: oklch(94% 0 0); + --uc-simple-btn-hover-light: oklch(92% 0 0); + --uc-simple-btn-foreground-light: oklch(20% 0 0); + + /* Dark colors OKLCH */ + --uc-primary-oklch-dark: 69% 0.1768 258.4; /* Quick customization: change this value to your brand color */ + --uc-primary-dark: oklch(var(--uc-primary-oklch-dark)); + --uc-primary-hover-dark: oklch(var(--uc-primary-oklch-dark) / 90%); + --uc-primary-transparent-dark: oklch(var(--uc-primary-oklch-dark) / 7%); + --uc-background-dark: oklch(22% 0 0); + --uc-foreground-dark: oklch(91% 0 0); + --uc-primary-foreground-dark: oklch(0% 0 0); + --uc-secondary-dark: oklch(91% 0 0 / 0.07); + --uc-secondary-hover-dark: oklch(91% 0 0 / 0.1); + --uc-secondary-foreground-dark: oklch(91% 0 0); + --uc-muted-dark: oklch(26% 0 0); + --uc-muted-foreground-dark: oklch(68% 0 0); + --uc-destructive-dark: oklch(67% 0.191 27.5 / 0.1); + --uc-destructive-foreground-dark: oklch(67% 0.191 27.5); + --uc-border-dark: oklch(36% 0 0); + --uc-dialog-shadow-dark: 0px 6px 20px oklch(0% 0 0 / 0.25); + --uc-simple-btn-dark: oklch(26% 0 0); + --uc-simple-btn-hover-dark: oklch(29% 0 0); + --uc-simple-btn-foreground-dark: oklch(100% 0 0); + } } @media only screen and (max-height: 600px) { - :where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) { - --modal-max-h: 100%; + :where([lr-wgt-common]) { + --uc-dialog-max-height: 100%; } } @media only screen and (max-width: 430px) { - :where(.lr-wgt-theme, .lr-wgt-common, lr-file-uploader-minimal, lr-file-uploader-inline, lr-file-uploader-regular) { - --modal-max-w: 100vw; - --modal-max-h: var(--uploadcare-blocks-window-height); + :where([lr-wgt-common]) { + --uc-dialog-max-width: 100vw; + --uc-dialog-max-height: var(--uploadcare-blocks-window-height); } } + +@media (prefers-color-scheme: light) { + :where([lr-wgt-common]) { + --uc-background: var(--uc-background-light); + --uc-foreground: var(--uc-foreground-light); + --uc-primary: var(--uc-primary-light); + --uc-primary-hover: var(--uc-primary-hover-light); + --uc-primary-transparent: var(--uc-primary-transparent-light); + --uc-primary-foreground: var(--uc-primary-foreground-light); + --uc-secondary: var(--uc-secondary-light); + --uc-secondary-hover: var(--uc-secondary-hover-light); + --uc-secondary-foreground: var(--uc-secondary-foreground-light); + --uc-muted: var(--uc-muted-light); + --uc-muted-foreground: var(--uc-muted-foreground-light); + --uc-destructive: var(--uc-destructive-light); + --uc-destructive-foreground: var(--uc-destructive-foreground-light); + --uc-border: var(--uc-border-light); + --uc-dialog-shadow: var(--uc-dialog-shadow-light); + --uc-simple-btn: var(--uc-simple-btn-light); + --uc-simple-btn-hover: var(--uc-simple-btn-hover-light); + --uc-simple-btn-foreground: var(--uc-simple-btn-foreground-light); + } +} + +@media (prefers-color-scheme: dark) { + :where([lr-wgt-common]) { + --uc-background: var(--uc-background-dark); + --uc-foreground: var(--uc-foreground-dark); + --uc-primary: var(--uc-primary-dark); + --uc-primary-hover: var(--uc-primary-hover-dark); + --uc-primary-transparent: var(--uc-primary-transparent-dark); + --uc-primary-foreground: var(--uc-primary-foreground-dark); + --uc-secondary: var(--uc-secondary-dark); + --uc-secondary-hover: var(--uc-secondary-hover-dark); + --uc-secondary-foreground: var(--uc-secondary-foreground-dark); + --uc-muted: var(--uc-muted-dark); + --uc-muted-foreground: var(--uc-muted-foreground-dark); + --uc-destructive: var(--uc-destructive-dark); + --uc-destructive-foreground: var(--uc-destructive-foreground-dark); + --uc-border: var(--uc-border-dark); + --uc-dialog-shadow: var(--uc-dialog-shadow-dark); + --uc-simple-btn: var(--uc-simple-btn-dark); + --uc-simple-btn-hover: var(--uc-simple-btn-hover-dark); + --uc-simple-btn-foreground: var(--uc-simple-btn-foreground-dark); + } +} + +:where(.uc-light) { + --uc-background: var(--uc-background-light); + --uc-foreground: var(--uc-foreground-light); + --uc-primary: var(--uc-primary-light); + --uc-primary-hover: var(--uc-primary-hover-light); + --uc-primary-transparent: var(--uc-primary-transparent-light); + --uc-primary-foreground: var(--uc-primary-foreground-light); + --uc-secondary: var(--uc-secondary-light); + --uc-secondary-hover: var(--uc-secondary-hover-light); + --uc-secondary-foreground: var(--uc-secondary-foreground-light); + --uc-muted: var(--uc-muted-light); + --uc-muted-foreground: var(--uc-muted-foreground-light); + --uc-destructive: var(--uc-destructive-light); + --uc-destructive-foreground: var(--uc-destructive-foreground-light); + --uc-border: var(--uc-border-light); + --uc-dialog-shadow: var(--uc-dialog-shadow-light); + --uc-simple-btn: var(--uc-simple-btn-light); + --uc-simple-btn-hover: var(--uc-simple-btn-hover-light); + --uc-simple-btn-foreground: var(--uc-simple-btn-foreground-light); +} + +:where(.uc-dark) { + --uc-background: var(--uc-background-dark); + --uc-foreground: var(--uc-foreground-dark); + --uc-primary: var(--uc-primary-dark); + --uc-primary-hover: var(--uc-primary-hover-dark); + --uc-primary-transparent: var(--uc-primary-transparent-dark); + --uc-primary-foreground: var(--uc-primary-foreground-dark); + --uc-secondary: var(--uc-secondary-dark); + --uc-secondary-hover: var(--uc-secondary-hover-dark); + --uc-secondary-foreground: var(--uc-secondary-foreground-dark); + --uc-muted: var(--uc-muted-dark); + --uc-muted-foreground: var(--uc-muted-foreground-dark); + --uc-destructive: var(--uc-destructive-dark); + --uc-destructive-foreground: var(--uc-destructive-foreground-dark); + --uc-border: var(--uc-border-dark); + --uc-dialog-shadow: var(--uc-dialog-shadow-dark); + --uc-simple-btn: var(--uc-simple-btn-dark); + --uc-simple-btn-hover: var(--uc-simple-btn-hover-dark); + --uc-simple-btn-foreground: var(--uc-simple-btn-foreground-dark); +} diff --git a/demo/cloud-image-editor.html b/demo/cloud-image-editor.html index cdffa5e61..811ebbe9a 100644 --- a/demo/cloud-image-editor.html +++ b/demo/cloud-image-editor.html @@ -1,9 +1,9 @@ - + - + - - + diff --git a/demo/form.html b/demo/form.html index 090432cff..15d42b2e1 100644 --- a/demo/form.html +++ b/demo/form.html @@ -30,15 +30,16 @@ - + + + + - - - + Submit diff --git a/demo/inline-mode.html b/demo/inline-mode.html deleted file mode 100644 index 66a71b121..000000000 --- a/demo/inline-mode.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/demo/raw-build.html b/demo/raw-build.html deleted file mode 100644 index 8a5f2099a..000000000 --- a/demo/raw-build.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/demo/raw-inline.html b/demo/raw-inline.html index c14256f9b..1c76c07ef 100644 --- a/demo/raw-inline.html +++ b/demo/raw-inline.html @@ -5,10 +5,10 @@ diff --git a/demo/raw-regular.html b/demo/raw-regular.html index e5f6c4a84..cb6cc9539 100644 --- a/demo/raw-regular.html +++ b/demo/raw-regular.html @@ -4,6 +4,13 @@ +