@webhandle/tree-file-browser 1.0.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,11 +21,10 @@ code loaded on demand.
21
21
  Set up a file manager
22
22
 
23
23
  ```js
24
- import { ImageBrowserView, FileSelectDialog, loadStyles } from '@webhandle/tree-file-browser/client-lib/dynamic-load.mjs'
24
+ import { ImageBrowserView, FileSelectDialog } from '@webhandle/tree-file-browser'
25
25
 
26
26
  let treeHolder = document.querySelector('.webhandle-file-tree-image-browser')
27
27
  if(treeHolder) {
28
- loadStyles()
29
28
  let imageBrowserView = new ImageBrowserView({
30
29
  // The source of the files
31
30
  sink: the file sink
@@ -33,6 +32,8 @@ if(treeHolder) {
33
32
  , eventNotificationPanel: eventPanel
34
33
  // optional, the directory which to open to
35
34
  , startingDirectory: 'img/empty'
35
+ // true by default. Will load styles to show the file browser
36
+ , loadStyles: true
36
37
  })
37
38
  imageBrowserView.appendTo(treeHolder)
38
39
  imageBrowserView.render()
@@ -47,8 +48,52 @@ Alternatively, the styles can be built into the pages stylesheet by including th
47
48
  so there's no harm in calling it if the css has already been included.
48
49
 
49
50
  Loading the css dynamically or loading the file browser dynamically requires that the compiled resources have been added to
50
- files available to the browser. These are at `@webhandle/tree-file-browser/resources` and must be available at the url
51
- `/@webhandle/tree-file-browser/resources`
51
+ files available to the browser. These are at `@webhandle/tree-file-browser/files` and must be available at the url
52
+ `/@webhandle/tree-file-browser/files`
53
+
54
+ ## Current Usage
55
+
56
+ ## Webhandle Component
57
+
58
+ ```js
59
+ import treeFileBrowserSetup from "@webhandle/tree-file-browser/initialize-webhandle-component.mjs"
60
+ let treeFileBrowserManager = await treeFileBrowserSetup(webhandle)
61
+
62
+ ```
63
+
64
+ ### Selections
65
+
66
+ You can listen for selections like:
67
+
68
+ ```js
69
+ imageBrowserView.emitter.on('select', async function(evt) {
70
+ console.log(await imageBrowserView.getSelectedUrl())
71
+ })
72
+ ```
73
+
74
+ ### Options
75
+
76
+ ```js
77
+ /**
78
+ * Construct a new file browser
79
+ * @param {object} options
80
+ * @param {FileSink} options.sink The file to use as a file source
81
+ * @param {boolean} [options.imagesOnly] Set to true if you would like to display only images
82
+ * @param {boolean} [options.loadStyles] True by default. If true, default styles will be loaded.
83
+ * @param {boolean} [options.allowFileSelection] Set to true so that selected files are marked
84
+ * @param {EventNotificationPanel} [options.eventNotificationPanel] The panel which status messages will be added to.
85
+ * @param {string} [options.startingDirectory] Opens to that directory path if it exists
86
+ * @param {boolean} [options.deleteWithoutConfirm] False by default
87
+ * @param {boolean} [options.ignoreGlobalEvents] False by default, if true it will not listen to events like paste or keypresses
88
+ * which occur on the document
89
+ * @param {Emitter} [options.emitter] Emitter for various file events
90
+ */
91
+
92
+ ```
93
+
94
+
95
+
96
+ ## Old Usage
52
97
 
53
98
  If you're using webhandle, you can set up all the server side resources, including kapla-tree-on-page and the material icons,
54
99
  by using:
@@ -114,31 +159,3 @@ Using it independently on a single page is also pretty easy
114
159
 
115
160
  ```
116
161
 
117
- ### Selections
118
-
119
- You can listen for selections like:
120
-
121
- ```js
122
- imageBrowserView.emitter.on('select', async function(evt) {
123
- console.log(await imageBrowserView.getSelectedUrl())
124
- })
125
- ```
126
-
127
- ### Options
128
-
129
- ```js
130
- /**
131
- * Construct a new file browser
132
- * @param {object} options
133
- * @param {FileSink} options.sink The file to use as a file source
134
- * @param {boolean} [options.imagesOnly] Set to true if you would like to display only images
135
- * @param {boolean} [options.allowFileSelection] Set to true so that selected files are marked
136
- * @param {EventNotificationPanel} [options.eventNotificationPanel] The panel which status messages will be added to.
137
- * @param {string} [options.startingDirectory] Opens to that directory path if it exists
138
- * @param {boolean} [options.deleteWithoutConfirm] False by default
139
- * @param {boolean} [options.ignoreGlobalEvents] False by default, if true it will not listen to events like paste or keypresses
140
- * which occur on the document
141
- * @param {Emitter} [options.emitter] Emitter for various file events
142
- */
143
-
144
- ```
@@ -1,4 +1,4 @@
1
- import Dialog from 'ei-dialog'
1
+ import { Dialog } from '@webhandle/dialog'
2
2
  import ImageBrowserView from './image-browser-view.mjs'
3
3
 
4
4
  /**
@@ -13,36 +13,36 @@ export class FileSelectDialog extends Dialog {
13
13
  super(Object.assign({
14
14
  title: 'Select A File'
15
15
  , body: `<div class="webhandle-file-tree-image-browser" style="width: 87vw;"> </div>`
16
- , afterOpen: function (bodyElement, dialog) {
16
+ , afterOpen: function () {
17
17
 
18
- let treeHolder = bodyElement.querySelector('.webhandle-file-tree-image-browser')
18
+ let treeHolder = this.el.querySelector('.body').querySelector('.webhandle-file-tree-image-browser')
19
19
  if (treeHolder) {
20
20
  let options = {
21
- sink: dialog.sink
22
- , imagesOnly: dialog.imagesOnly
23
- , eventNotificationPanel: dialog.eventNotificationPanel
24
- , startingDirectory: dialog.startingDirectory
25
- , deleteWithoutConfirm: dialog.deleteWithoutConfirm
21
+ sink: this.sink
22
+ , imagesOnly: this.imagesOnly
23
+ , eventNotificationPanel: this.eventNotificationPanel
24
+ , startingDirectory: this.startingDirectory
25
+ , deleteWithoutConfirm: this.deleteWithoutConfirm
26
26
  }
27
27
 
28
28
  let imageBrowserView = this.imageBrowserView = new ImageBrowserView(options)
29
- if(dialog._createAccessUrl) {
30
- imageBrowserView._createAccessUrl = dialog._createAccessUrl
29
+ if(this._createAccessUrl) {
30
+ imageBrowserView._createAccessUrl = this._createAccessUrl
31
31
  }
32
- if(dialog._transformRelativeUrlToPublic) {
33
- imageBrowserView._transformRelativeUrlToPublic = dialog._transformRelativeUrlToPublic
32
+ if(this._transformRelativeUrlToPublic) {
33
+ imageBrowserView._transformRelativeUrlToPublic = this._transformRelativeUrlToPublic
34
34
  }
35
35
  imageBrowserView.appendTo(treeHolder)
36
36
  imageBrowserView.render()
37
37
 
38
- imageBrowserView.emitter.on('select', async function (evt) {
38
+ imageBrowserView.emitter.on('select', async (evt) => {
39
39
 
40
40
  })
41
- imageBrowserView.emitter.on('upload', async function (evt) {
42
- if(dialog.chooseOnUpload) {
43
- dialog.close()
44
- dialog.imageBrowserView.cleanup()
45
- dialog.resolve({
41
+ imageBrowserView.emitter.on('upload', async (evt) => {
42
+ if(this.chooseOnUpload) {
43
+ this.imageBrowserView.cleanup()
44
+ this.cleanup()
45
+ this.resolve({
46
46
  url: evt.accessUrls[0]
47
47
  })
48
48
  }
@@ -50,41 +50,27 @@ export class FileSelectDialog extends Dialog {
50
50
  }
51
51
  }
52
52
  , chooseOnUpload: true
53
- }, options,
54
- {
55
- on: {
56
- '.btn-ok': async () => {
57
- let result = {
58
- selection: this.imageBrowserView.getSelectedFiles()
59
- }
60
- result.url = await this.imageBrowserView.getSelectedUrl(result.selection)
61
- this.imageBrowserView.cleanup()
62
- this.resolve(result)
63
-
64
- return true
65
- },
66
- '.mask': () => {
67
- this.resolve()
68
- this.imageBrowserView.cleanup()
69
- return true
70
- },
71
- '.btn-cancel': () => {
72
- this.resolve()
73
- this.imageBrowserView.cleanup()
74
- return true
75
- }
76
- }
77
- }
53
+ }, options
78
54
  ))
79
55
  }
80
-
81
- async open() {
82
- this.promise = new Promise((resolve, reject) => {
83
- this.resolve = resolve
84
- this.reject = reject
85
- })
86
- super.open()
87
-
88
- return this.promise
56
+ async okay() {
57
+ let result = {
58
+ selection: this.imageBrowserView.getSelectedFiles()
59
+ }
60
+ result.url = await this.imageBrowserView.getSelectedUrl(result.selection)
61
+ this.imageBrowserView.cleanup()
62
+ this.cleanup()
63
+ this.resolve(result)
64
+ }
65
+ cancel() {
66
+ this.resolve(false)
67
+ this.imageBrowserView.cleanup()
68
+ this.cleanup()
89
69
  }
70
+ close() {
71
+ this.resolve(false)
72
+ this.imageBrowserView.cleanup()
73
+ this.cleanup()
74
+ }
75
+
90
76
  }
@@ -1,4 +1,4 @@
1
- import { FormAnswerDialog } from '../form-answer-dialog.mjs'
1
+ import { FormAnswerDialog } from "@webhandle/dialog"
2
2
 
3
3
  export function createDirectory(evt, selected) {
4
4
  let dialog = new FormAnswerDialog({
@@ -1,4 +1,4 @@
1
- import { FormAnswerDialog } from '../form-answer-dialog.mjs'
1
+ import { FormAnswerDialog } from "@webhandle/dialog"
2
2
 
3
3
  export async function deleteFile(evt, selected) {
4
4
  let sel = this.getSelectedFiles()
@@ -1,4 +1,4 @@
1
- import { FormAnswerDialog } from '../form-answer-dialog.mjs'
1
+ import { FormAnswerDialog } from '@webhandle/dialog'
2
2
  import baseImageName from '../base-image-name.mjs'
3
3
  import makeImageSet from '../make-image-set.mjs'
4
4
  import nameParts from '../name-parts.mjs'
@@ -23,7 +23,7 @@ export async function _uploadGuidedImageFile(file) {
23
23
  title: 'Upload File'
24
24
  , body: guidedImageUploadForm(data)
25
25
  , data: data
26
- , dialogFrameClass: 'webhandle-file-tree-image-browser'
26
+ , className: 'webhandle-file-tree-image-browser'
27
27
  })
28
28
  let prom = dialog.open()
29
29
  let result = await prom
@@ -75,7 +75,7 @@ export async function _uploadGuidedFile(file) {
75
75
  title: 'Upload File'
76
76
  , body: guidedFileUploadForm(data)
77
77
  , data: data
78
- , dialogFrameClass: 'webhandle-file-tree-image-browser'
78
+ , className: 'webhandle-file-tree-image-browser'
79
79
  })
80
80
  let prom = dialog.open()
81
81
  let result = await prom
@@ -1,4 +1,4 @@
1
- import { InfoDialog } from '../info-dialog.mjs'
1
+ import { Dialog } from '@webhandle/dialog'
2
2
  import escapeHtmlAttributeValue from '@dankolz/escape-html-attribute-value'
3
3
 
4
4
  export function changeFilesView(evt, selected) {
@@ -94,15 +94,10 @@ export function showVariantDetails(evt, selected) {
94
94
 
95
95
  content += '</div>'
96
96
 
97
- let dialog = new InfoDialog({
97
+ let dialog = new Dialog({
98
98
  title: 'File Details: ' + variant.baseName
99
99
  , body: content
100
- , buttons: [
101
- {
102
- classes: 'btn btn-primary btn-ok',
103
- label: 'OK'
104
- }
105
- ]
100
+ , showCancelButton: false
106
101
  })
107
102
  let prom = dialog.open()
108
103
  prom.then(async data => {
@@ -1,7 +1,8 @@
1
1
  import { View } from '@webhandle/backbone-view'
2
2
  import { imageBrowserFrame, variantChoiceBox } from '../views/load-browser-views.js'
3
- import KalpaTreeOnPage from 'kalpa-tree-on-page'
3
+ import {KalpaTreeView} from "kalpa-tree-on-page/kalpa-tree-view"
4
4
  import formatBytes from './format-bytes.mjs'
5
+ import loadStyles from './load-styles.mjs'
5
6
 
6
7
  import Emitter from '@webhandle/minimal-browser-event-emitter'
7
8
 
@@ -26,6 +27,7 @@ export default class ImageBrowserView extends View {
26
27
  * @param {object} options
27
28
  * @param {FileSink} options.sink The file to use as a file source
28
29
  * @param {boolean} [options.imagesOnly] Set to true if you would like to display only images
30
+ * @param {boolean} [options.loadStyles] True by default. If true, default styles will be loaded.
29
31
  * @param {boolean} [options.allowFileSelection] Set to true so that selected files are marked
30
32
  * @param {EventNotificationPanel} [options.eventNotificationPanel] The panel which status messages will be added to.
31
33
  * @param {string} [options.startingDirectory] Opens to that directory path if it exists
@@ -43,6 +45,11 @@ export default class ImageBrowserView extends View {
43
45
  this.setIfNotSet('fileUploadSelector', 'input[name="fileUpload"]')
44
46
  this.setIfNotSet('listTriggerSize', 100)
45
47
  this.setIfNotSet('listLockSize', 200)
48
+ this.setIfNotSet('loadStyles', true)
49
+
50
+ if(this.loadStyles) {
51
+ loadStyles()
52
+ }
46
53
  }
47
54
 
48
55
  preinitialize() {
@@ -89,41 +96,42 @@ export default class ImageBrowserView extends View {
89
96
  this._sortFiles(directories)
90
97
 
91
98
  this.data.push(...directories.map(this._fileToKalpaNode.bind(this)))
92
- KalpaTreeOnPage({
93
- treeContainerSelector: `#${this.id} .treebox`
94
- , data: this.data
95
- }).then(tree => {
96
- this.tree = tree
97
- tree.on('select', (node) => {
98
- this.setCurrentNode(node)
99
- })
100
- tree.on('selected', (node) => {
101
- // There's a bug, either in the browser or kalpa tree that causes it
102
- // not to examine if a scroll bar is needed for the tree if the content
103
- // area changes in a big way. Part of this bug may be that it's being
104
- // used in a grid which has some weird width/height effects
105
- // Anyway, we need to make sure the browser knows to examine the tree so
106
- // we change the height then change it back.
107
- // This event is triggered when kalpa-tree thinks it's done with transitions
108
-
109
- let tree = this.el.querySelector('.tree')
110
- tree.style.height = '99.99999%'
111
- setTimeout(() => {
112
- tree.style.height = '100%'
113
- }, 100)
114
- })
115
- if (this.startingDirectory) {
116
- for (let node of Object.values(this.tree.nodes)) {
117
- if (node.file && node.file.relPath && node.file.relPath == this.startingDirectory) {
118
- tree.select(node.id)
119
- break
120
- }
99
+ let treeView = new KalpaTreeView({
100
+ data: this.data
101
+ })
102
+ let treeBox = this.el.querySelector('.treebox')
103
+ treeView.appendTo(treeBox)
104
+ await treeView.render()
105
+ let tree = this.tree = treeView.tree
106
+ tree.on('select', (node) => {
107
+ this.setCurrentNode(node)
108
+ })
109
+ tree.on('selected', (node) => {
110
+ // There's a bug, either in the browser or kalpa tree that causes it
111
+ // not to examine if a scroll bar is needed for the tree if the content
112
+ // area changes in a big way. Part of this bug may be that it's being
113
+ // used in a grid which has some weird width/height effects
114
+ // Anyway, we need to make sure the browser knows to examine the tree so
115
+ // we change the height then change it back.
116
+ // This event is triggered when kalpa-tree thinks it's done with transitions
117
+
118
+ let tree = this.el.querySelector('.tree')
119
+ tree.style.height = '99.99999%'
120
+ setTimeout(() => {
121
+ tree.style.height = '100%'
122
+ }, 100)
123
+ })
124
+ if (this.startingDirectory) {
125
+ for (let node of Object.values(this.tree.nodes)) {
126
+ if (node.file && node.file.relPath && node.file.relPath == this.startingDirectory) {
127
+ tree.select(node.id)
128
+ break
121
129
  }
122
130
  }
123
- else {
124
- tree.select(1)
125
- }
126
- })
131
+ }
132
+ else {
133
+ tree.select(1)
134
+ }
127
135
  }
128
136
 
129
137
  async setCurrentNode(node) {
@@ -0,0 +1,8 @@
1
+ import ImageBrowserView from './image-browser-view.mjs';
2
+ import { FileSelectDialog } from './file-select-dialog.mjs'
3
+
4
+ import loadStyles from './load-styles.mjs'
5
+
6
+ export {ImageBrowserView, FileSelectDialog, loadStyles}
7
+
8
+
@@ -1,14 +1,14 @@
1
1
  import areStylesLoaded from "./styles-loaded.mjs";
2
- import ensureIcons from '@dankolz/webhandle-admin-icons/client-js/ensure-styles-are-loaded.js'
2
+ import {loadMaterialIcons} from "@webhandle/material-icons"
3
3
 
4
4
  export default function loadStyles() {
5
5
  if(!areStylesLoaded()) {
6
6
  let link = document.createElement('link')
7
- link.href = '/@webhandle/tree-file-browser/resources/css/tree-browser.css'
7
+ link.href = '/@webhandle/tree-file-browser/files/css/tree-browser.css'
8
8
  link.rel = 'stylesheet'
9
9
  document.head.appendChild(link)
10
10
 
11
11
  }
12
- ensureIcons()
12
+ loadMaterialIcons()
13
13
 
14
14
  }
@@ -0,0 +1,67 @@
1
+ import createInitializeWebhandleComponent from "@webhandle/initialize-webhandle-component/create-initialize-webhandle-component.mjs"
2
+ import ComponentManager from "@webhandle/initialize-webhandle-component/component-manager.mjs"
3
+ import path from "node:path"
4
+ import setupMaterialIcons from "@webhandle/material-icons/initialize-webhandle-component.mjs"
5
+ import setupDialog from "@webhandle/dialog/initialize-webhandle-component.mjs"
6
+ import kalpaTreeSetup from "kalpa-tree-on-page/initialize-webhandle-component.mjs"
7
+
8
+ let initializeWebhandleComponent = createInitializeWebhandleComponent()
9
+
10
+ initializeWebhandleComponent.componentName = '@webhandle/tree-file-browser'
11
+ initializeWebhandleComponent.componentDir = import.meta.dirname
12
+ initializeWebhandleComponent.defaultConfig = {
13
+ publicFilesPrefix: "/@webhandle/tree-file-browser/files"
14
+ , provideResources: true
15
+ }
16
+
17
+ initializeWebhandleComponent.setup = async function(webhandle, config) {
18
+ let manager = new ComponentManager()
19
+ manager.config = config
20
+
21
+ let managerMaterialIcons = await setupMaterialIcons(webhandle)
22
+ let managerDialog = await setupDialog(webhandle)
23
+ let kalpaTreeManager = await kalpaTreeSetup(webhandle)
24
+
25
+ manager.provideExternalResources = function(externalResourceManager) {
26
+
27
+ let resource = {
28
+ mimeType: 'application/javascript'
29
+ , url: config.publicFilesPrefix + '/js/browser.js'
30
+ , name: '@webhandle/tree-file-browser'
31
+ , resourceType: 'module'
32
+ , cachable: webhandle.development ? false : true
33
+ }
34
+ externalResourceManager.provideResource(resource)
35
+
36
+ resource = {
37
+ mimeType: 'application/javascript'
38
+ , name: '@webhandle/tree-file-browser/configuration'
39
+ , resourceType: 'module'
40
+ , cachable: webhandle.development ? false : true
41
+ , data: {publicFilesPrefix: config.publicFilesPrefix}
42
+ }
43
+ externalResourceManager.provideResource(resource)
44
+ }
45
+
46
+ if(config.provideResources) {
47
+ webhandle.routers.preDynamic.use((req, res, next) => {
48
+ manager.provideExternalResources(res.locals.externalResourceManager)
49
+ next()
50
+ })
51
+ }
52
+
53
+ let dir = 'public/tree-file-browser/resources'
54
+ manager.staticPaths.push(
55
+ webhandle.addStaticDir(
56
+ path.join(initializeWebhandleComponent.componentDir, dir),
57
+ {
58
+ urlPrefix: config.publicFilesPrefix
59
+ , fixedSetOfFiles: true
60
+ }
61
+ )
62
+ )
63
+
64
+ return manager
65
+ }
66
+
67
+ export default initializeWebhandleComponent
package/package.json CHANGED
@@ -1,24 +1,16 @@
1
1
  {
2
2
  "name": "@webhandle/tree-file-browser",
3
- "version": "1.0.6",
3
+ "version": "2.0.0",
4
4
  "description": "",
5
5
  "main": "client-lib/image-browser-view.mjs",
6
6
  "scripts": {
7
- "test": "node_modules/mocha/bin/mocha",
8
- "less-build": "npx lessc --source-map --source-map-include-source less/pages.less public/css/pages.css; npx lessc --source-map --source-map-include-source less/components.less public/tree-file-browser/resources/css/tree-browser.css",
9
- "less-compress": "npx uglifycss public/css/pages.css > public/css/pages.min.css",
10
- "client-js-build": "npx webpack --config pages.webpack.cjs",
11
- "client-js-compress": "npx uglifyjs public/js/pages.cjs -o public/js/pages.min.cjs -c --source-map url=public/js/pages.min.cjs.map",
12
- "client-js-browserify-build": "npm run client-js-pages-browserify-build",
13
- "client-js-pages-browserify build": "npx browserify client-js/pages.cjs --debug | npx exorcist public/js/pages.cjs.map > public/js/pages.cjs",
7
+ "test": "node ./test/test-names.mjs",
8
+ "less-build": "lessc --source-map --source-map-include-source less/components.less public/tree-file-browser/resources/css/tree-browser.css",
9
+ "client-js-build": "webpack-cli --config browser.webpack.cjs",
10
+ "client-js-build-watch": "webpack-cli --watch --config browser.webpack.cjs",
14
11
  "dev-less-watch": "onchange 'less/**/*.less' -- npm run less-build",
15
- "dev-client-js-watch": "onchange 'client-lib/**/*js' 'views/webhandle-tree-image-browser/**/*tri' 'client-js/**/*js' -- npm run client-js-build",
16
- "dev-server-js-watch": "onchange 'server-lib/**/*js' 'server-js/**/*js' -- pm2 restart webhandle-tree-image-browser-web",
17
- "start": "node ./web-server.js",
18
- "testDebug": "node --inspect-brk node_modules/mocha/bin/mocha",
19
- "bg": "parallelshell 'npm run dev-less-watch' 'npm run dev-client-js-watch'",
20
- "pm2-bg": "parallelshell 'npm run dev-less-watch' 'npm run dev-client-js-watch' 'npm run dev-server-js-watch'",
21
- "dev": "parallelshell 'npm run start' 'npm run dev-less-watch' 'npm run dev-client-js-watch'"
12
+ "start": "run-webhandle-dev ./test/test-server.mjs",
13
+ "dev": "parallelshell 'npm run start' 'npm run dev-less-watch' 'npm run client-js-build-watch'"
22
14
  },
23
15
  "keywords": [],
24
16
  "author": "",
@@ -26,47 +18,24 @@
26
18
  "devDependencies": {
27
19
  "@dankolz/ei-css-grid": "^1.0.0",
28
20
  "@webhandle/event-notification-panel": "^1.0.0",
29
- "browserify": "^14.4.0",
30
- "chai": "^4.3.4",
21
+ "@webhandle/webpack-text-loader": "^1.0.0",
31
22
  "ei-form-styles-1": "^1.0.2",
32
23
  "ei-pic-browser": "^1.0.15",
33
- "exorcist": "^2.0.0",
34
- "express": "^4.17.1",
35
24
  "file-sink": "^1.0.13",
36
- "file-sink-remote-http": "^1.0.2",
25
+ "file-sink-remote-http": "^2.0.0",
37
26
  "file-sink-server": "^1.0.5",
38
- "filter-log": "0.0.5",
39
- "jsdoc": "^3.6.11",
40
- "less": "^3.10.3",
41
- "mocha": "^9.1.3",
42
- "node-polyfill-webpack-plugin": "^2.0.1",
43
- "onchange": "^3.2.1",
44
- "parallelshell": "3.0.1",
45
- "raw-loader": "^4.0.2",
46
- "tripartite": "^1.1.1",
47
- "uglify-js": "^3.17.4",
48
- "webhandle": "^1.0.32",
49
- "webhandle-js-widget-setup": "^1.0.5",
50
- "webpack-cli": "^5.1.4"
27
+ "filter-log": "^1.0.13",
28
+ "tripartite": "^1.1.1"
51
29
  },
52
30
  "dependencies": {
53
31
  "@dankolz/escape-html-attribute-value": "^1.0.0",
54
- "@dankolz/webhandle-admin-icons": "^1.0.2",
55
32
  "@dankolz/webp-detection": "^1.0.14",
56
33
  "@webhandle/backbone-view": "^1.0.1",
57
- "@webhandle/gather-form-data": "^1.0.0",
34
+ "@webhandle/dialog": "^1.0.1",
35
+ "@webhandle/initialize-webhandle-component": "^1.0.2",
36
+ "@webhandle/material-icons": "^1.0.1",
58
37
  "@webhandle/minimal-browser-event-emitter": "^1.0.2",
59
- "ei-dialog": "^1.0.11",
60
- "form-value-injector": "^1.0.6",
61
- "input-value-injector": "^1.0.11",
62
- "kalpa-tree-on-page": "^1.0.2",
63
- "select-value-injector": "^1.0.3",
64
- "textarea-value-injector": "^1.0.3"
65
- },
66
- "browserify": {
67
- "transform": [
68
- "tripartite/browserify-transform"
69
- ]
38
+ "kalpa-tree-on-page": "^1.0.5"
70
39
  },
71
40
  "files": [
72
41
  "/client-lib",
@@ -74,7 +43,9 @@
74
43
  "/server-lib",
75
44
  "public/tree-file-browser",
76
45
  "/views/load-browser-views.js",
77
- "/views/webhandle-tree-image-browser"
46
+ "/views/webhandle-tree-image-browser",
47
+ "README.md",
48
+ "initialize-webhandle-component.mjs"
78
49
  ],
79
50
  "type": "module"
80
51
  }
@@ -0,0 +1,2 @@
1
+ import{View as t}from"@webhandle/backbone-view";import{tripartite as e}from"tripartite";import{KalpaTreeView as i}from"kalpa-tree-on-page/kalpa-tree-view";import{loadMaterialIcons as n}from"@webhandle/material-icons";import{Dialog as a,FormAnswerDialog as s}from"@webhandle/dialog";var l={7(t){t.exports=function(t,e){return e=e?"&#13;":"\n",(""+t).replace(/&/g,"&amp;").replace(/'/g,"&apos;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\r\n/g,e).replace(/[\r\n]/g,e)}},343(t,e,i){let{imageExtensions:n,smallerSizeExt:a,imageSizeExt:s}=i(497);const l=i(269),r=i(354),o=i(329),c=i(444),d=i(235);function h(t){let e=l(t.variants);t.preview=e;let i=d(t.variants);t.primary=i}t.exports=function(t){let e=t.filter(t=>!t.directory),i=e.filter(t=>t.name.toLowerCase().endsWith(".json")),n=e.filter(r),a={};function s(t){if(t in a)return a[t];let e={baseName:t,variants:[]};return a[t]=e,e}for(let t of i)s(c(t.name)).definitionFile=t;for(let t of n.map(o))s(t.baseName).variants.push(t);for(let t of Array.from(Object.keys(a)))0==a[t].variants.length&&delete a[t];return Object.values(a).forEach(h),a}},497(t){let e={imageExtensions:["jpg","jpeg","png","gif","tiff","webp"],smallerSizeExt:["quarter","half"]};e.imageSizeExt=[...e.smallerSizeExt,"std","2x"],t.exports=e},444(t){t.exports=function(t){return t.substring(0,t.lastIndexOf("."))}},269(t,e,i){let{imageExtensions:n,smallerSizeExt:a,imageSizeExt:s}=i(497);t.exports=function(t){for(let e of s)for(let i of n)for(let n of t)if(n.size==e&&n.ext==i)return n}},235(t,e,i){let{imageExtensions:n,smallerSizeExt:a,imageSizeExt:s}=i(497),l=["std","2x",...a],r=n.filter(t=>"webp"!=t);t.exports=function(t){for(let e of l)for(let i of r)for(let n of t)if(n.size==e&&n.ext==i)return n}},180(t,e,i){let{imageExtensions:n,smallerSizeExt:a,imageSizeExt:s}=i(497);t.exports=function(t){let e=t.toLowerCase();for(let t of n)if(e.endsWith("."+t))return!0;return!1}},354(t,e,i){const n=i(180);t.exports=function(t){return n(t.name)}},329(t,e,i){let{imageExtensions:n,smallerSizeExt:a,imageSizeExt:s}=i(497);t.exports=function(t){let e={size:"std",file:t},i=t.name;e.ext=i.substring(i.lastIndexOf(".")+1);let n=i.substring(0,i.lastIndexOf("."));e.baseName=n;for(let t of s){let i="-"+t;if(n.endsWith(i)){e.size=t,e.baseName=n.substring(0,n.length-i.length);break}}return e}}},r={};function o(t){var e=r[t];if(void 0!==e)return e.exports;var i=r[t]={exports:{}};return l[t](i,i.exports,o),i.exports}function c(t){return e.addTemplate(t.name,t.content)}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);let d=c({name:"webhandle-tree-image-browser/image-browser-frame",content:'<div class="image-browser-frame">\n\t<div class="directory-side">\n\t\t<div class="treebox">\n\n\t\t</div>\n\t\t<div class="directory-controls">\n\t\t\t<button type="button" class="btn create-directory" title="create new directory">\n\t\t\t\t<span class="material-icons thumbnail-icon">\n\t\t\t\t\tcreate_new_folder\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t\t<button type="button" class="btn delete-directory" title="delete selected directory">\n\t\t\t\t<span class="material-icons thumbnail-icon">\n\t\t\t\t\tfolder_delete\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t</div>\n\t</div>\n\t<div class="node-view">\n\t\t<div class="view-controls">\n\t\t\t<div class="left">\n\t\t\t\t<input name="filter" type="text" placeholder="filter" />\n\t\t\t\t<button class="clear-filter">&times;</button>\n\t\t\t</div>\n\t\t\t<div class="right">\n\t\t\t\t<span class="view-icons">\n\t\t\t\t\t<button type="button" class="show-large-tiles" title="show big tiles" data-show-class="grid-large">\n\t\t\t\t\t\t<span class="material-icons thumbnail-icon">\n\t\t\t\t\t\t\tgrid_view\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type="button" class="show-small-tiles" title="show small tiles"\n\t\t\t\t\t\tdata-show-class="grid-small">\n\t\t\t\t\t\t<span class="material-icons thumbnail-icon">\n\t\t\t\t\t\t\tgrid_on\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type="button" class="show-list-rows" title="show as rows" data-show-class="rows">\n\t\t\t\t\t\t<span class="material-icons thumbnail-icon">\n\t\t\t\t\t\t\tlist\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</button>\n\t\t\t\t\t<button type="button" class="show-list-text" title="show as list" data-show-class="list-text">\n\t\t\t\t\t\t<span class="material-icons thumbnail-icon">\n\t\t\t\t\t\t\ttable_rows\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</button>\n\t\t\t\t</span>\n\n\t\t\t</div>\n\t\t</div>\n\t\t<div class="node-content">\n\t\t\t<div class="box-holder">\n\t\t\t\t<div class="choice-boxes">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class="bottom-controls">\n\t\t\t<div class="file-controls">\n\t\t\t\t<button type="button" class="btn delete-file" title="delete selected file(s)">\n\t\t\t\t\t<span class="material-icons thumbnail-icon">\n\t\t\t\t\t\tdelete\n\t\t\t\t\t</span>\n\t\t\t\t</button>\n\t\t\t\t<button type="button" class="btn upload-file" title="upload file(s)">\n\t\t\t\t\t<span class="material-icons thumbnail-icon">\n\t\t\t\t\t\tupload\n\t\t\t\t\t</span>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div class="folder-info">\n\t\t\t\t\n\t\t\t</div>\n\n\t\t</div>\n\t</div>\n\t<div class="drop-cover file-drop-cover">\n\t\t<div class="drop-type literal">\n\t\t\t<div class="msg">\n\t\t\t\t<h2>\n\t\t\t\t\tJust Do It\n\t\t\t\t</h2>\n\t\t\t\t<p>\n\t\t\t\t\tWe won\'t mess the files at all, just upload them.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\t<div class="drop-cover img-drop-cover">\n\t\t<div class="drop-type guided-upload">\n\t\t\t<div class="msg">\n\t\t\t\t<h2>Guided Upload</h2>\n\t\t\t\t<p>\n\t\t\t\t\tLet us help you rename, and resize (if needed), the files by asking you questions\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class="drop-type automatic">\n\t\t\t<div class="msg">\n\t\t\t\t<h2>\n\t\t\t\t\tWeb Safe\n\t\t\t\t</h2>\n\t\t\t\t<p>\n\t\t\t\t\tWe\'ll rename the files so they fit better with the web and create multiple formats images.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class="drop-type literal">\n\t\t\t<div class="msg">\n\t\t\t\t<h2>\n\t\t\t\t\tJust Do It\n\t\t\t\t</h2>\n\t\t\t\t<p>\n\t\t\t\t\tWe won\'t mess the files at all, just upload them.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\n\t</div>\n\t<div class="hidden-elements">\n\t\t<input name="fileUpload" type="file" placeholder="Upload a file" />\n\t\t\n\t</div>\n\n</div>'}),h=c({name:"webhandle-tree-image-browser/variant-choice-box",content:'<div class="variant-choice-box">\n\t<div class="img">\n\t\t__!this.thumbnail??\'<span class="material-icons thumbnail-icon">\' + thumbnailIcon + \'</span>\'__\n\t\t__this.thumbnail??\'<img loading="lazy" class="thumbnail-image" src="\' + safeThumbnail + \'" />\'__\n\t</div>\n\t<div class="size-line">\n\t\t__size__\n\t</div>\n\t<div class="bottom">\n\t\t<div class="content">\n\t\t\t<div class="basename">\n\t\t\t\t__safeBaseName__\n\t\t\t</div>\n\t\t\t<div class="extensions">\n\t\t\t\t__extensions::./extension-pill__\n\t\t\t</div>\n\t\t</div>\n\t\t<div class="actions">\n\t\t\t<button class="details">\n\t\t\t\t<span class="material-icons">more_vert</span>\n\t\t\t</button>\n\t\t</div>\n\t</div>\n\n</div>'}),u=(c({name:"webhandle-tree-image-browser/extension-pill",content:'<span class="extension-pill">__this__</span>'}),c({name:"webhandle-tree-image-browser/guilded-image-upload-form",content:'<div class="guided-image-upload-form ei-form">\n\t<label>\n\t\tSource file name:<br>\n\t\t__nativeName__\n\t</label>\n\t<label>\n\t\tNative resolution:<br>\n\t\t__stats.width__ x __stats.height__\n\t</label>\n\t<label>\n\t\tAfter uploaded name (no extension):\n\t\t<input name="name" type="text" />\n\t</label>\n\t<div class="radio-options">\n\t\tOutput format:\n\t\t<label>\n\t\t\t<input type="radio" name="outputFormat" value="image/png" /> <span class="extension-pill">PNG</span>\n\t\t</label>\n\t\t<label>\n\t\t\t<input type="radio" name="outputFormat" value="image/jpeg" /> <span class="extension-pill">JPG</span>\n\t\t</label>\n\t</div>\n\t<label>\n\t\tOn screen width (px):\n\t\t<input name="width" type="number" />\n\t</label>\n\t<label>\n\t\tOutput quality (0 to 1):\n\t\t<input name="quality" value="0.7" type="number" min="0" max="1" step=".01" />\n\t</label>\n\t\n\t<label>\n\t\tAlt text:\n\t\t<textarea name="altText"></textarea>\n\t</label>\n\t\n</div>'})),f=c({name:"webhandle-tree-image-browser/guilded-file-upload-form",content:'<div class="guided-image-upload-form ei-form">\n\t<label>\n\t\tSource file name:<br>\n\t\t__nativeName__\n\t</label>\n\t<label>\n\t\tAfter uploaded name (with extension):\n\t\t<input name="name" type="text" />\n\t</label>\n\t\n</div>'});function p(t,e){if(0==t)return"0 Bytes";var i=e||2,n=Math.floor(Math.log(t)/Math.log(1024));return parseFloat((t/Math.pow(1024,n)).toFixed(i))+" "+["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"][n]}function m(){if(!function(){let t=document.createElement("div");t.classList.add("webhandle-file-tree-image-browser-test"),t.style.position="absolute",t.style.left="-10000px",document.body.appendChild(t);let e=window.getComputedStyle(t)["background-color"];return t.remove(),"rgb(101, 105, 99)"===e}()){let t=document.createElement("link");t.href="/@webhandle/tree-file-browser/files/css/tree-browser.css",t.rel="stylesheet",document.head.appendChild(t)}n()}class g{constructor(){this.handles={}}on(t,e){let i=this.handles[t];return i||(i=this.handles[t]=[]),i.push(e),this}emit(t,...e){if(t in this.handles)for(let i of this.handles[t])i.apply(this,e)}removeListener(t,e){t in this.handles&&(this.handles[t]=this.handles[t].filter(t=>t!==e))}}let v,b="undefined"==typeof EventTarget?g:EventTarget;v="undefined"!=typeof EventTarget?class extends b{constructor(t){super(t),this.innerEventTarget=t||this}on(t,e){if(this.innerEventTarget.addEventListener){let i=t=>{e.apply(this,t.detail)};e.nativeListener=i,this.innerEventTarget.addEventListener(t,i)}else super.on(t,e);return this}emit(t,...e){return this.innerEventTarget.dispatchEvent?this.innerEventTarget.dispatchEvent(this._makeEvent(t,e)):super.emit(t,...e),this}removeListener(t,e){return this.innerEventTarget.removeEventListener?(e=e.nativeListener||e,this.innerEventTarget.removeEventListener(t,e)):super.removeListener(t,e),this}_makeEvent(t,e){if("function"==typeof CustomEvent)return new CustomEvent(t,{detail:e});{let i=new Event(t);return i.detail=e,i}}}:g;const y=v;async function w(t,e){let i=this.getSelectedFiles();if(i.files.length>0){let t=i.files,e=i.names;if(!this.deleteWithoutConfirm){let i=new s({title:"Delete File"+(t.length>1?"s":""),body:"<p>"+e.join(", ")+"</p>"}).open();if(!await i)return}for(let e of t){let t,i=e.relPath;this.eventNotificationPanel&&(t=this.eventNotificationPanel.addNotification({model:{status:"pending",headline:`deleting ${e.name}`}})),await this.sink.rm(i),this.eventNotificationPanel&&(t.remove(),t=this.eventNotificationPanel.addNotification({model:{status:"success",headline:`removed ${e.name}`},ttl:2e3}))}for(let t of i.boxes)t.remove()}this.emitter.emit("delete",{type:"delete",selected:i})}async function x(t,e){let i=this.currentNode.file.relPath,n=this.currentNode.file.name;if(!i)return;let a,l=new s({title:"Delete Directory",body:"<p>"+n+"</p>"}).open();if(!await l)return;this.eventNotificationPanel&&(a=this.eventNotificationPanel.addNotification({model:{status:"pending",headline:`deleting ${n}`}})),await this.sink.rm(i,{recursive:!0});let r=this.tree.selected(),o=this.tree.parent(r);this.tree.removeNode(r),this.tree.select(o.id),this.eventNotificationPanel&&(a.remove(),a=this.eventNotificationPanel.addNotification({model:{status:"success",headline:`removed ${n}`},ttl:2e3}))}function _(...t){return(t=t.filter(t=>!!t)).join("/")}function F(t){if(!t)return"";let e=t.split("/");return e.pop(),e.join("/")}function S(t){let e={id:this.idInd++,label:t.name,directory:t.directory,file:t,loaded:!1},i=this.nodes[this._determineParentPath(t.relPath)];return this.nodes[t.relPath]=e,i&&(e.parentId=i.id,e.path=t.relPath),t.path=e.path,e}function N(t){let e=new Set;if(t.variants)for(let i of t.variants)e.add(i.ext);else e.add(t.ext);let i=Array.from(e).filter(t=>!!t);return i.sort((t,e)=>t.toLowerCase().localeCompare(e.toLowerCase())),i}function T(t){let e=2e9,i=0;if(t.variants)for(let n of t.variants){let t=n.file.stat.size;t>i&&(i=t),t<e&&(e=t)}else{let n=t.file.stat.size;n>i&&(i=n),n<e&&(e=n)}return[e,i]}function E(t){return t.sort((t,e)=>t.relPath.toLowerCase().localeCompare(e.relPath.toLowerCase())),t}function L(t,e){return t.baseName.toLowerCase().localeCompare(e.baseName.toLowerCase())}function D(t){return t.split("/").join("-").split("..").join("-")}function P(t){return!!t.type.startsWith("image")&&!!(t.type.includes("jpeg")||t.type.includes("png")||t.type.includes("webp"))}function k(t,e){t in this||(this[t]=e)}function z(t){let e;return this.eventNotificationPanel&&(e=this.eventNotificationPanel.addNotification({model:{status:"pending",headline:`uploading ${t.name}`}})),e}var U=o(7);function I(t,e){let i=e.getAttribute("data-show-class");this.changeFilesViewToClass(i)}function C(t){let e=this.el.querySelector(".choice-boxes");[...this.el.querySelector(".view-icons").querySelectorAll("button")].map(t=>t.getAttribute("data-show-class")).forEach(t=>{e.classList.remove(t)}),e.classList.add(t)}function j(t,e){setTimeout(()=>{let t=this.el.querySelector('[name="filter"]').value,e=this.el.querySelectorAll(".choice-boxes .variant-choice-box");for(let i of e)i.classList.remove("hidden"),t&&(t=t.toLowerCase(),(i.variant.baseName.toLowerCase()+i.variant.extensions.map(t=>t.toLowerCase()).join()).indexOf(t)<0&&i.classList.add("hidden"));this.setFolderInfo()})}function q(t,e){this.el.querySelector('[name="filter"]').value="",this.applyFilter()}function A(t,e){let i=this.el.querySelectorAll(".choice-boxes .variant-choice-box.selected");if(!t.ctrlKey&&!t.shiftKey)for(let t of i)t.classList.remove("selected");if(t.shiftKey){let t=e;do{if(t.classList.contains("selected"))break;t.classList.add("selected"),t=t.previousElementSibling}while(t)}else e.classList.toggle("selected");let n=this.getSelectedFiles();this.emitter.emit("select",{type:"select",selected:n})}function O(t,e){let i=e.closest(".variant-choice-box").variant,n=this._getAssociatedRealFiles(i),s='<div class="variant-details-information">';i.safeThumbnail&&(s+=`<div class="details-preview-image">\n\t\t<img loading="lazy" src="${i.safeThumbnail}" />\n\t\t</div>`),s+='<ul class="variants">';for(let t of n)s+='<li><a target="_blank" href="'+U(this.escapeAccessUrl(t.accessUrl))+'">',s+=U(t.name)+"</a> - "+this._formatBytes(t.stat.size),s+="</li>";s+="</ul>",s+="</div>",new a({title:"File Details: "+i.baseName,body:s,showCancelButton:!1}).open().then(async t=>{})}function B(){let t=0,e=0,i=0,n=0,a=this.el.querySelectorAll(".choice-boxes .variant-choice-box");for(let s of a)s.classList.contains("hidden")||(e++,s.variant.variants?s.variant.variants.forEach(e=>{t++,i+=e.file.stat.size}):(t++,i+=s.variant.file.stat.size,n++));this.el.querySelector(".folder-info").innerHTML=`${e} items / ${t} files / ${this._formatBytes(i)} `,e>this.listTriggerSize&&this.changeFilesViewToClass("list-text"),this.el.querySelector(".view-icons").classList.remove("no-img"),e-n>this.listLockSize&&this.el.querySelector(".view-icons").classList.add("no-img")}function V(){this.el.querySelector(".folder-info").innerHTML="",this.el.querySelector(".choice-boxes").innerHTML='<div class="loading-info">Loading Information Now</div>',this.el.querySelector(".view-icons").classList.add("no-img")}function R(){return".img-drop-cover"}async function M(t,e){let i="literal",n=t.target.closest(".drop-type");n&&(n.classList.contains("guided-upload")?i="guided":n.classList.contains("automatic")&&(i="automatic")),this._cleanupDropDone(),t.preventDefault();let a=await this._getFilesFromEvent(t);this.uploadFiles(a,{uploadType:i})}function W(t){let e=!0;return t.dataTransfer&&"string"===t.dataTransfer.items[0].kind&&(e=!1),e}function $(t,e){this.isFileTypeDrag(t)&&(this.overCount++,this.el.querySelector(this.getDropCoverSelector()).classList.add("file-dropping"))}function G(t,e){this.isFileTypeDrag(t)&&(this.overCount--,0==this.overCount&&this._cleanupDropDone())}function K(t,e){t.preventDefault()}function H(){this.overCount=0,[...this.el.querySelectorAll(".file-dropping")].forEach(t=>t.classList.remove("file-dropping"))}async function J(t){this.ignoreGlobalEvents||t.clipboardData&&t.clipboardData.files&&t.clipboardData.files.length>0&&(t.preventDefault(),this.uploadFiles(t.clipboardData.files,{uploadType:"guided"}))}function Z(t,e){new s({title:"Create Directory",body:'<label>Directory name <input type="text" name="name" /></label>'}).open().then(async t=>{if(t){let e=this.currentNode.file.relPath+"/"+t.name;await this.sink.mkdir(e);let i=await this.sink.getFullFileInfo(e),n=this._fileToKalpaNode(i);this.tree.options.stream.emit("data",n);let a=this.tree.selected();a&&this.tree.expand(a.id)}})}var Y=o(343);function Q(t){if(!t||"string"!=typeof t)return t;let e=[...t];t="";for(let i=0;i<e.length;i++)t+=e[i],i%10==0&&(t+="<wbr>");return function(t,e){for(let t of["_"])e=e.split(t).join("<wbr>"+t);return e}(0,t)}function X(t){let e=Y(t.children),i=Object.values(e),n=[];for(let t of i)n.push(...this._getAssociatedRealFiles(t).map(t=>t.name));let a=t.children.filter(t=>!n.includes(t.name)).filter(t=>!t.directory);for(let t of i)t.thumbnailIcon="image",t.preview&&(t.thumbnail=this._createAccessUrl(t.preview.file),t.safeThumbnail=U(t.thumbnail));if(!this.imagesOnly)for(let t of a){let e={file:t,thumbnailIcon:"description"},n=t.name;e.ext=n.substring(n.lastIndexOf(".")+1),e.baseName=n.substring(0,n.lastIndexOf(".")),i.push(e)}for(let t of i)t.extensions=this._determineExtensions(t),t.sizes=this._determineSizes(t),t.sizes[0]==t.sizes[1]?t.size=this._formatBytes(t.sizes[0]):t.size=this._formatBytes(t.sizes[0])+" - "+this._formatBytes(t.sizes[1]),t.safeBaseName=Q(U(t.baseName));return i.sort(this._compareVariants),i}async function tt(t){let e=[];if(t.dataTransfer.items){let i=[];[...t.dataTransfer.items].forEach((t,e)=>{i.push(t)});for(let t of i)if("file"===t.kind)if(t.webkitGetAsEntry){let i=t.webkitGetAsEntry();if(i){if(i.isDirectory)continue;e.push(t.getAsFile())}}else e.push(t.getAsFile());else t instanceof File&&e.push(t)}else[...t.dataTransfer.files].forEach((t,i)=>{e.push(t)});return e}function et(t){let e=[];return t.variants?e.push(...t.variants.map(t=>t.file)):e.push(t.file),t.definitionFile&&e.push(t.definitionFile),e}function it(t){return this.escapeAccessUrl(t.accessUrl)}function nt(t){return function(t,e){for(let t of["%"," ","#","?","<",">","$","@","^","&"])e=e.split(t).join(encodeURIComponent(t));return e}(0,t)}function at(){let t={boxes:[],variants:[],files:[],names:[]},e=this.el.querySelectorAll(".choice-boxes .variant-choice-box.selected");if(e.length>0){for(let i of e)t.boxes.push(i),t.variants.push(i.variant),t.files.push(...this._getAssociatedRealFiles(i.variant));let i=t.files.map(t=>t.name);t.names.push(...i)}return t}function st(t){return 0==t.startsWith("/")&&(t="/"+t),t}async function lt(t){if(t||(t=this.getSelectedFiles()),0==t.variants.length)return;let e,i=t.variants[0];e=i.primary?i.primary.file:i.file;let n=this._transformRelativeUrlToPublic(e.relPath);if(i.definitionFile){let t=await this.sink.read(i.definitionFile.relPath);try{let e=JSON.parse(t);n+=this.getSelectedUrlExtFromMeta(e)}catch(t){}}return n}function rt(t){let e="",i=t.displaySize.split("x");return e+=`#format=webp2x&width=${i[0]}&height=${i[1]}`,t.altText&&(e+="&alt="+encodeURIComponent(t.altText)),e}function ot(t){let e;"string"==typeof t?e=t:t instanceof File&&(e=t.name);let i=e.split(".");i.length>1&&i.pop(),e=i.join("."),e=e.replace(/-@2x$/,""),e=e.replace(/@2x$/,""),e=e.replace(/-2x$/,""),e=e.replace(/2x$/,"");let n=[e.substring(0,1)];for(let t of e.substring(1))t.match(/[A-Z]/)&&n.push("-"),n.push(t);return e=n.join(""),e=e.toLowerCase(),e=e.replace(/[^1234567890a-z-]/g,"-"),e=e.replace(/--+/g,"-"),e}async function ct(t){return new Promise((e,i)=>{let n,a;if(t instanceof Image)n=t;else if("string"==typeof t)n=new Image,n.src=t;else{let e=new Blob([t]);a=URL.createObjectURL(e),n=new Image,n.src=a}function s(){a&&URL.revokeObjectURL(a),e(n)}n.complete?s():n.addEventListener("load",()=>{s()})})}async function dt(t,{maxWidth:e=1920,quality:i=.7,outputFormat:n="image/png"}={}){return new Promise(async(a,s)=>{try{let s=await ct(t),o=s.naturalWidth/e,c=s.naturalHeight/o;var l=document.createElement("canvas");l.width=e,l.height=c;var r=l.getContext("2d");r.clearRect(0,0,l.width,l.height),r.drawImage(s,0,0,l.width,l.height),l.toBlob(t=>{a(t)},n,i)}catch(t){console&&console.log&&console.log("error resizing image: "+t),s(t)}})}async function ht(t){let e=await ct(t);return{width:e.naturalWidth,height:e.naturalHeight}}let ut={"image/png":"png","image/jpeg":"jpg","image/jpg":"jpg","image/webp":"webp"};function ft(t){return t in ut?ut[t]:t.split("/").pop()}let pt="image/webp";async function mt(t,{singleDensityWidth:e=null,quality:i=.7,outputFormat:n="image/png",doubleDensityInput:a=!0,baseFileName:s,altText:l}={}){let r=await ct(t),o=await ht(r),c=o.width/o.height;s||(s=""+(new Date).getTime()),e||(e=a?o.width/2:o.width);let d=2*e,h={"-2x":d,"":e,"-half":Math.floor(e/2),"-quarter":Math.floor(e/4)},u={};for(let t of Object.keys(h)){let e=h[t],a=await dt(r,{maxWidth:e,quality:i,outputFormat:n});u[s+t+"."+ft(n)]=a,a=await dt(r,{maxWidth:e,quality:i,outputFormat:pt}),u[s+t+"."+ft(pt)]=a}let f={name:s,size:d+"x"+d/c,displaySize:e+"x"+e/c,fallback:ft(n),altText:l||s};return u[s+".json"]=JSON.stringify(f,null,"\t"),u}function gt(t){let e;"string"==typeof t?e=t:t instanceof File&&(e=t.name);let i=[ot(e)],n=e.split(".");return n.length>1&&i.push(n.pop()),i}async function vt(t){let e=ot(t),i=await async function(t){let e=await ct(t),i=await ht(e);return i.ratio=i.width/i.height,i.ext=ft(t.type),i}(t),n={nativeName:t.name,name:e,outputFormat:t.type,stats:i,width:Math.floor(i.width/2)},a=new s({title:"Upload File",body:u(n),data:n,className:"webhandle-file-tree-image-browser"}).open(),l=await a;if(l){let e,i={baseFileName:l.name,outputFormat:l.outputFormat,singleDensityWidth:parseInt(l.width),quality:parseFloat(l.quality),altText:l.altText},n=this._addPending(t),a=await mt(t,i),s=JSON.parse(a[i.baseFileName+".json"]);for(let t of Object.keys(a)){let i=await this._uploadData(t,a[t]);t===s.name+"."+s.fallback&&(e=i)}let r=this._transformRelativeUrlToPublic(e);return r+=this.getSelectedUrlExtFromMeta(s),n&&n.remove(),r}}async function bt(t){let e=gt(t),i={nativeName:t.name,name:e.join(".")},n=new s({title:"Upload File",body:f(i),data:i,className:"webhandle-file-tree-image-browser"}).open(),a=await n;if(a){let e=this._addPending(t),i=await this._uploadData(a.name,t),n=this._transformRelativeUrlToPublic(i);return e&&e.remove(),n}}async function yt(t){let e,i=this._addPending(t),n=gt(t)[0],a=await mt(t,{baseFileName:n,outputFormat:t.type}),s=JSON.parse(a[n+".json"]);for(let t of Object.keys(a)){let i=await this._uploadData(t,a[t]);t===s.name+"."+s.fallback&&(e=i)}let l=this._transformRelativeUrlToPublic(e);return l+=this.getSelectedUrlExtFromMeta(s),i&&i.remove(),l}async function wt(t,{uploadType:e}={}){let i=[];for(let n of t){let t=!1;if("guided"===e&&this._isImageFile(n))t=await this._uploadGuidedImageFile(n);else if("guided"===e)t=await this._uploadGuidedFile(n);else if("automatic"===e&&this._isImageFile(n))t=await this._uploadAutomaticImageFile(n);else{let i,a=this._addPending(n);if("automatic"===e){let t=gt(n);i=await this._uploadData(t.join("."),n)}else i=await this._uploadData(n.name,n);t=this._transformRelativeUrlToPublic(i),a&&a.remove()}this.eventNotificationPanel&&t&&this.eventNotificationPanel.addNotification({model:{status:"success",headline:`uploaded ${n.name}`},ttl:2e3}),i.push(t)}return this.setCurrentNode(this.currentNode),this.emitter.emit("upload",{type:"upload",accessUrls:i}),i}function xt(t,e){this.el.querySelector(this.fileUploadSelector).click()}async function _t(t,e){t.preventDefault();let i=this.el.querySelector(this.fileUploadSelector);t.dataTransfer={files:i.files};let n=await this._getFilesFromEvent(t);if(n.length>0){let t=this.uploadFiles(n,{uploadType:"guided"});return i.value="",t}}async function Ft(t,e){let i=this.currentNode.file.relPath+"/"+this.sanitizeFileName(t);return await this.sink.write(i,e),i}async function St(){return new Promise((t,e)=>{let i=[],n=this.sink.find({file:!1});n.on("data",t=>{i.push(t)}),n.on("done",()=>{t(i)})})}class Nt extends t{constructor(t){super(t),this.setIfNotSet("overCount",0),this.setIfNotSet("emitter",new y),this.setIfNotSet("fileUploadSelector",'input[name="fileUpload"]'),this.setIfNotSet("listTriggerSize",100),this.setIfNotSet("listLockSize",200),this.setIfNotSet("loadStyles",!0),this.loadStyles&&m()}preinitialize(){this.className="image-browser",this.idInd=1,this.nodes={},this.events={"click .create-directory":"createDirectory","click .upload-file":"_uploadFileButton",'change [name="fileUpload"]':"_uploadFile","click .delete-file":"deleteFile","click .delete-directory":"deleteDirectory","click .variant-choice-box .details":"showVariantDetails","dblclick .variant-choice-box":"showVariantDetails","click .variant-choice-box":"selectVariant","click .view-icons button":"changeFilesView",'keyup [name="filter"]':"applyFilter",'change [name="filter"]':"applyFilter","click .clear-filter":"clearFilter","dragenter .":"dragEnter","dragleave .":"dragLeave","dragover .":"dragOver","drop .":"handleDrop"},this.pasteListener=J.bind(this),document.addEventListener("paste",this.pasteListener)}cleanup(){document.removeEventListener("paste",this.pasteListener)}async render(){this.el.innerHTML=d(this.model),this.data=[],this.rootDirectory=await this.sink.getFullFileInfo(""),this.rootDirectory.name="Files";let t=this.rootNode=this._fileToKalpaNode(this.rootDirectory);this.data.push(t);let e=await this.findDirectories();this._sortFiles(e),this.data.push(...e.map(this._fileToKalpaNode.bind(this)));let n=new i({data:this.data}),a=this.el.querySelector(".treebox");n.appendTo(a),await n.render();let s=this.tree=n.tree;if(s.on("select",t=>{this.setCurrentNode(t)}),s.on("selected",t=>{let e=this.el.querySelector(".tree");e.style.height="99.99999%",setTimeout(()=>{e.style.height="100%"},100)}),this.startingDirectory){for(let t of Object.values(this.tree.nodes))if(t.file&&t.file.relPath&&t.file.relPath==this.startingDirectory){s.select(t.id);break}}else s.select(1)}async setCurrentNode(t){this.currentNode=t,this.cleanFileInfo();let e=this.el.querySelector(".choice-boxes"),i=await this.sink.getFullFileInfo(t.file.relPath),n=this.createVariantValues(i);n.length>this.listTriggerSize&&this.changeFilesViewToClass("list-text");let a="";for(let t of n)a+=h(t);e.innerHTML="",e.insertAdjacentHTML("beforeend",a);for(let t=0;t<e.children.length;t++)e.children[t].variant=n[t];this.el.querySelector(".box-holder").scrollTop=0,this.applyFilter()}_uploadGuidedImageFile=vt;_uploadGuidedFile=bt;_uploadAutomaticImageFile=yt;uploadFiles=wt;_uploadFileButton=xt;_uploadFile=_t;createVariantValues=X;_getFilesFromEvent=tt;_getAssociatedRealFiles=et;_createAccessUrl=it;escapeAccessUrl=nt;getSelectedFiles=at;_transformRelativeUrlToPublic=st;getSelectedUrl=lt;getSelectedUrlExtFromMeta=rt;createDirectory=Z;getDropCoverSelector=R;handleDrop=M;isFileTypeDrag=W;dragEnter=$;dragLeave=G;dragOver=K;handlePaste=J;_cleanupDropDone=H;changeFilesView=I;changeFilesViewToClass=C;applyFilter=j;clearFilter=q;selectVariant=A;showVariantDetails=O;setFolderInfo=B;cleanFileInfo=V;sanitizeFileName=D;_sortFiles=E;_compareVariants=L;_determineExtensions=N;_determineSizes=T;_join=_;_determineParentPath=F;_fileToKalpaNode=S;_formatBytes=p;_isImageFile=P;setIfNotSet=k;_addPending=z;deleteFile=w;deleteDirectory=x;_uploadData=Ft;findDirectories=St}class Tt extends a{constructor(t){super(Object.assign({title:"Select A File",body:'<div class="webhandle-file-tree-image-browser" style="width: 87vw;"> </div>',afterOpen:function(){let t=this.el.querySelector(".body").querySelector(".webhandle-file-tree-image-browser");if(t){let e={sink:this.sink,imagesOnly:this.imagesOnly,eventNotificationPanel:this.eventNotificationPanel,startingDirectory:this.startingDirectory,deleteWithoutConfirm:this.deleteWithoutConfirm},i=this.imageBrowserView=new Nt(e);this._createAccessUrl&&(i._createAccessUrl=this._createAccessUrl),this._transformRelativeUrlToPublic&&(i._transformRelativeUrlToPublic=this._transformRelativeUrlToPublic),i.appendTo(t),i.render(),i.emitter.on("select",async t=>{}),i.emitter.on("upload",async t=>{this.chooseOnUpload&&(this.imageBrowserView.cleanup(),this.cleanup(),this.resolve({url:t.accessUrls[0]}))})}},chooseOnUpload:!0},t))}async okay(){let t={selection:this.imageBrowserView.getSelectedFiles()};t.url=await this.imageBrowserView.getSelectedUrl(t.selection),this.imageBrowserView.cleanup(),this.cleanup(),this.resolve(t)}cancel(){this.resolve(!1),this.imageBrowserView.cleanup(),this.cleanup()}close(){this.resolve(!1),this.imageBrowserView.cleanup(),this.cleanup()}}export{Tt as FileSelectDialog,Nt as ImageBrowserView,m as loadStyles};
2
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","mappings":"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","sources":["webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/escape-html-attribute-value/index.js","webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/webp-detection/lib/condense-image-variants.js","webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/webp-detection/lib/definitions.js","webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/webp-detection/lib/file-basename.js","webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/webp-detection/lib/find-preview-variant.js","webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/webp-detection/lib/find-primary-variant.js","webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/webp-detection/lib/is-file-image-name.js","webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/webp-detection/lib/is-file-image.js","webpack://@webhandle/tree-file-browser/./node_modules/@dankolz/webp-detection/lib/make-variant-image.js","webpack://@webhandle/tree-file-browser/webpack/bootstrap","webpack://@webhandle/tree-file-browser/./views/load-browser-views.js","webpack://@webhandle/tree-file-browser/webpack/runtime/define property getters","webpack://@webhandle/tree-file-browser/webpack/runtime/hasOwnProperty shorthand","webpack://@webhandle/tree-file-browser/./views/webhandle-tree-image-browser/image-browser-frame.tri","webpack://@webhandle/tree-file-browser/./views/webhandle-tree-image-browser/variant-choice-box.tri","webpack://@webhandle/tree-file-browser/./views/webhandle-tree-image-browser/extension-pill.tri","webpack://@webhandle/tree-file-browser/./views/webhandle-tree-image-browser/guilded-image-upload-form.tri","webpack://@webhandle/tree-file-browser/./views/webhandle-tree-image-browser/guilded-file-upload-form.tri","webpack://@webhandle/tree-file-browser/./client-lib/format-bytes.mjs","webpack://@webhandle/tree-file-browser/./client-lib/load-styles.mjs","webpack://@webhandle/tree-file-browser/./client-lib/styles-loaded.mjs","webpack://@webhandle/tree-file-browser/./node_modules/@webhandle/minimal-browser-event-emitter/client-js/streamish.mjs","webpack://@webhandle/tree-file-browser/./node_modules/@webhandle/minimal-browser-event-emitter/client-js/event-emitter.mjs","webpack://@webhandle/tree-file-browser/./node_modules/@webhandle/minimal-browser-event-emitter/client-js/index.js","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view-methods/delete.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view-methods/utils.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view-methods/view-interactions.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view-methods/drag-and-drop.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view-methods/create-directory.mjs","webpack://@webhandle/tree-file-browser/./client-lib/add-soft-breaks.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view-methods/file-obj-manipulation.mjs","webpack://@webhandle/tree-file-browser/./client-lib/base-image-name.mjs","webpack://@webhandle/tree-file-browser/./client-lib/data-to-image.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-resize.mjs","webpack://@webhandle/tree-file-browser/./client-lib/get-image-stats.mjs","webpack://@webhandle/tree-file-browser/./client-lib/get-extension-from-mime.mjs","webpack://@webhandle/tree-file-browser/./client-lib/make-image-set.mjs","webpack://@webhandle/tree-file-browser/./client-lib/name-parts.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view-methods/upload.mjs","webpack://@webhandle/tree-file-browser/./client-lib/get-file-image-stats.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view-methods/sink.mjs","webpack://@webhandle/tree-file-browser/./client-lib/image-browser-view.mjs","webpack://@webhandle/tree-file-browser/./client-lib/file-select-dialog.mjs"],"sourcesContent":["function escapeHtmlAttributeValue(s, preserveCR) {\n preserveCR = preserveCR ? '&#13;' : '\\n';\n return ('' + s) \n .replace(/&/g, '&amp;') \n .replace(/'/g, '&apos;') \n .replace(/\"/g, '&quot;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\\r\\n/g, preserveCR) \n .replace(/[\\r\\n]/g, preserveCR)\n}\n\nmodule.exports = escapeHtmlAttributeValue\n","let {imageExtensions, smallerSizeExt, imageSizeExt} = require('./definitions')\nconst findPreviewVariant = require('./find-preview-variant')\nconst isFileImage = require('./is-file-image')\nconst makeVariantImage = require('./make-variant-image')\nconst fileBasename = require('./file-basename')\nconst findPrimaryVariant = require('./find-primary-variant')\n\n/**\n * Condenses an array of files into logical images with their variants. This works on a set of image files which all share\n * a base name, but have different extensions depending on how much larger or smaller they are compared to\n * the \"natural\" size of that image and what format they use (png, jpg, webp). There may also exist an additional json\n * file which shares the base name which contains information about description or other attributes.\n * \n * @param {array} directoryContents An array of file objects like those returned from FileSink.getFullFileInfo\n * That is, they have a `name` attribute which is the file name and a `directory` attribute which is true if a directory.\n * @returns A map of variants keyed by the image's base name.\n */\nfunction condenseImageVaraints(directoryContents) {\n\tlet files = directoryContents.filter(child => !child.directory)\n\tlet definitions = files.filter(child => child.name.toLowerCase().endsWith('.json'))\n\tlet imageFiles = files.filter(isFileImage)\n\n\tlet variants = {}\n\tfunction getVariant(baseName) {\n\t\tif (baseName in variants) {\n\t\t\treturn variants[baseName]\n\t\t}\n\t\tlet variant = {\n\t\t\tbaseName: baseName\n\t\t\t, variants: []\n\t\t}\n\t\tvariants[baseName] = variant\n\t\treturn variant\n\t}\n\n\t// create variants for all the definitions. Images don't have to have\n\t// defintions but if they do, we want to do them first.\n\tfor (let definition of definitions) {\n\t\tlet baseName = fileBasename(definition.name)\n\t\tlet variant = getVariant(baseName)\n\t\tvariant.definitionFile = definition\n\t}\n\t\n\t// match up all the image files to their variant definitions\n\tfor(let imageVariant of imageFiles.map(makeVariantImage)) {\n\t\tlet variant = getVariant(imageVariant.baseName)\n\t\tvariant.variants.push(imageVariant)\n\t}\n\t\n\t// remove those without images\n\tfor(let baseName of Array.from(Object.keys(variants))) {\n\t\tif(variants[baseName].variants.length == 0) {\n\t\t\tdelete variants[baseName]\n\t\t}\n\t}\n\t\n\t// set the preview variant\n\tObject.values(variants).forEach(setSpecialVariants)\n\n\treturn variants\n}\n\nfunction setSpecialVariants(variantDefinition) {\n\tlet preview = findPreviewVariant(variantDefinition.variants)\n\tvariantDefinition.preview = preview\n\t\n\tlet primary = findPrimaryVariant(variantDefinition.variants)\n\tvariantDefinition.primary = primary\n}\n\n\nmodule.exports = condenseImageVaraints","let definitions = {\n\timageExtensions: ['jpg', 'jpeg', 'png', 'gif', 'tiff', 'webp']\n\t, smallerSizeExt: ['quarter', 'half']\n}\ndefinitions.imageSizeExt = [...definitions.smallerSizeExt, 'std', '2x']\n\nmodule.exports = definitions","\nfunction fileBasename(name) {\n\treturn name.substring(0, name.lastIndexOf('.'))\n}\n\nmodule.exports = fileBasename","let {imageExtensions, smallerSizeExt, imageSizeExt} = require('./definitions')\n\nfunction findPreviewVariant(variants) {\n\tfor(let size of imageSizeExt) {\n\t\tfor(let img of imageExtensions) {\n\t\t\tfor(let variant of variants) {\n\t\t\t\tif(variant.size == size && variant.ext == img) {\n\t\t\t\t\treturn variant\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nmodule.exports = findPreviewVariant","let {imageExtensions, smallerSizeExt, imageSizeExt} = require('./definitions')\n\nlet fallbackSizeExt = ['std', '2x', ...smallerSizeExt]\nlet fallbackImgageExtensions = imageExtensions.filter(item => item != 'webp')\n\nfunction findPrimaryVariant(variants) {\n\tfor(let size of fallbackSizeExt) {\n\t\tfor(let img of fallbackImgageExtensions) {\n\t\t\tfor(let variant of variants) {\n\t\t\t\tif(variant.size == size && variant.ext == img) {\n\t\t\t\t\treturn variant\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nmodule.exports = findPrimaryVariant","\nlet {imageExtensions, smallerSizeExt, imageSizeExt} = require('./definitions')\n\nfunction isFileImageName(name) {\n\tlet nameLower = name.toLowerCase()\n\tfor (let ext of imageExtensions) {\n\t\tif (nameLower.endsWith('.' + ext)) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nmodule.exports = isFileImageName","const isFileImageName = require('./is-file-image-name')\n\nfunction isFileImage(file) {\n\treturn isFileImageName(file.name)\n}\n\nmodule.exports = isFileImage","let {imageExtensions, smallerSizeExt, imageSizeExt} = require('./definitions')\n\nfunction makeVariantImage(file) {\n\tlet info = {\n\t\tsize: 'std'\n\t\t, file: file\n\t}\n\tlet name = file.name\n\n\tinfo.ext = name.substring(name.lastIndexOf('.') + 1)\n\tlet noExt = name.substring(0, name.lastIndexOf('.'))\n\tinfo.baseName = noExt\n\tfor (let size of imageSizeExt) {\n\t\tlet sizeString = '-' + size\n\t\tif (noExt.endsWith(sizeString)) {\n\t\t\tinfo.size = size\n\t\t\tinfo.baseName = noExt.substring(0, noExt.length - sizeString.length)\n\t\t\tbreak\n\t\t}\n\t}\n\treturn info\n}\n\nmodule.exports = makeVariantImage","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","import {tripartite} from \"tripartite\"\nimport t3 from './webhandle-tree-image-browser/image-browser-frame.tri';\nimport t4 from './webhandle-tree-image-browser/variant-choice-box.tri'\nimport t5 from './webhandle-tree-image-browser/extension-pill.tri'\nimport t6 from './webhandle-tree-image-browser/guilded-image-upload-form.tri'\nimport t7 from './webhandle-tree-image-browser/guilded-file-upload-form.tri'\n\nfunction add(item) {\n\treturn tripartite.addTemplate(item.name, item.content)\n}\n\nexport let imageBrowserFrame = add(t3)\nexport let variantChoiceBox = add(t4)\nexport let extensionPill = add(t5)\nexport let guidedImageUploadForm = add(t6)\nexport let guidedFileUploadForm = add(t7)\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","export default { name: \"webhandle-tree-image-browser/image-browser-frame\", content: \"<div class=\\\"image-browser-frame\\\">\\n\\t<div class=\\\"directory-side\\\">\\n\\t\\t<div class=\\\"treebox\\\">\\n\\n\\t\\t<\\/div>\\n\\t\\t<div class=\\\"directory-controls\\\">\\n\\t\\t\\t<button type=\\\"button\\\" class=\\\"btn create-directory\\\" title=\\\"create new directory\\\">\\n\\t\\t\\t\\t<span class=\\\"material-icons thumbnail-icon\\\">\\n\\t\\t\\t\\t\\tcreate_new_folder\\n\\t\\t\\t\\t<\\/span>\\n\\t\\t\\t<\\/button>\\n\\t\\t\\t<button type=\\\"button\\\" class=\\\"btn delete-directory\\\" title=\\\"delete selected directory\\\">\\n\\t\\t\\t\\t<span class=\\\"material-icons thumbnail-icon\\\">\\n\\t\\t\\t\\t\\tfolder_delete\\n\\t\\t\\t\\t<\\/span>\\n\\t\\t\\t<\\/button>\\n\\t\\t<\\/div>\\n\\t<\\/div>\\n\\t<div class=\\\"node-view\\\">\\n\\t\\t<div class=\\\"view-controls\\\">\\n\\t\\t\\t<div class=\\\"left\\\">\\n\\t\\t\\t\\t<input name=\\\"filter\\\" type=\\\"text\\\" placeholder=\\\"filter\\\" \\/>\\n\\t\\t\\t\\t<button class=\\\"clear-filter\\\">&times;<\\/button>\\n\\t\\t\\t<\\/div>\\n\\t\\t\\t<div class=\\\"right\\\">\\n\\t\\t\\t\\t<span class=\\\"view-icons\\\">\\n\\t\\t\\t\\t\\t<button type=\\\"button\\\" class=\\\"show-large-tiles\\\" title=\\\"show big tiles\\\" data-show-class=\\\"grid-large\\\">\\n\\t\\t\\t\\t\\t\\t<span class=\\\"material-icons thumbnail-icon\\\">\\n\\t\\t\\t\\t\\t\\t\\tgrid_view\\n\\t\\t\\t\\t\\t\\t<\\/span>\\n\\t\\t\\t\\t\\t<\\/button>\\n\\t\\t\\t\\t\\t<button type=\\\"button\\\" class=\\\"show-small-tiles\\\" title=\\\"show small tiles\\\"\\n\\t\\t\\t\\t\\t\\tdata-show-class=\\\"grid-small\\\">\\n\\t\\t\\t\\t\\t\\t<span class=\\\"material-icons thumbnail-icon\\\">\\n\\t\\t\\t\\t\\t\\t\\tgrid_on\\n\\t\\t\\t\\t\\t\\t<\\/span>\\n\\t\\t\\t\\t\\t<\\/button>\\n\\t\\t\\t\\t\\t<button type=\\\"button\\\" class=\\\"show-list-rows\\\" title=\\\"show as rows\\\" data-show-class=\\\"rows\\\">\\n\\t\\t\\t\\t\\t\\t<span class=\\\"material-icons thumbnail-icon\\\">\\n\\t\\t\\t\\t\\t\\t\\tlist\\n\\t\\t\\t\\t\\t\\t<\\/span>\\n\\t\\t\\t\\t\\t<\\/button>\\n\\t\\t\\t\\t\\t<button type=\\\"button\\\" class=\\\"show-list-text\\\" title=\\\"show as list\\\" data-show-class=\\\"list-text\\\">\\n\\t\\t\\t\\t\\t\\t<span class=\\\"material-icons thumbnail-icon\\\">\\n\\t\\t\\t\\t\\t\\t\\ttable_rows\\n\\t\\t\\t\\t\\t\\t<\\/span>\\n\\t\\t\\t\\t\\t<\\/button>\\n\\t\\t\\t\\t<\\/span>\\n\\n\\t\\t\\t<\\/div>\\n\\t\\t<\\/div>\\n\\t\\t<div class=\\\"node-content\\\">\\n\\t\\t\\t<div class=\\\"box-holder\\\">\\n\\t\\t\\t\\t<div class=\\\"choice-boxes\\\">\\n\\t\\t\\t\\t<\\/div>\\n\\t\\t\\t<\\/div>\\n\\t\\t<\\/div>\\n\\t\\t<div class=\\\"bottom-controls\\\">\\n\\t\\t\\t<div class=\\\"file-controls\\\">\\n\\t\\t\\t\\t<button type=\\\"button\\\" class=\\\"btn delete-file\\\" title=\\\"delete selected file(s)\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"material-icons thumbnail-icon\\\">\\n\\t\\t\\t\\t\\t\\tdelete\\n\\t\\t\\t\\t\\t<\\/span>\\n\\t\\t\\t\\t<\\/button>\\n\\t\\t\\t\\t<button type=\\\"button\\\" class=\\\"btn upload-file\\\" title=\\\"upload file(s)\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"material-icons thumbnail-icon\\\">\\n\\t\\t\\t\\t\\t\\tupload\\n\\t\\t\\t\\t\\t<\\/span>\\n\\t\\t\\t\\t<\\/button>\\n\\t\\t\\t<\\/div>\\n\\t\\t\\t<div class=\\\"folder-info\\\">\\n\\t\\t\\t\\t\\n\\t\\t\\t<\\/div>\\n\\n\\t\\t<\\/div>\\n\\t<\\/div>\\n\\t<div class=\\\"drop-cover file-drop-cover\\\">\\n\\t\\t<div class=\\\"drop-type literal\\\">\\n\\t\\t\\t<div class=\\\"msg\\\">\\n\\t\\t\\t\\t<h2>\\n\\t\\t\\t\\t\\tJust Do It\\n\\t\\t\\t\\t<\\/h2>\\n\\t\\t\\t\\t<p>\\n\\t\\t\\t\\t\\tWe won't mess the files at all, just upload them.\\n\\t\\t\\t\\t<\\/p>\\n\\t\\t\\t<\\/div>\\n\\t\\t<\\/div>\\n\\t<\\/div>\\n\\t<div class=\\\"drop-cover img-drop-cover\\\">\\n\\t\\t<div class=\\\"drop-type guided-upload\\\">\\n\\t\\t\\t<div class=\\\"msg\\\">\\n\\t\\t\\t\\t<h2>Guided Upload<\\/h2>\\n\\t\\t\\t\\t<p>\\n\\t\\t\\t\\t\\tLet us help you rename, and resize (if needed), the files by asking you questions\\n\\t\\t\\t\\t<\\/p>\\n\\t\\t\\t<\\/div>\\n\\t\\t<\\/div>\\n\\t\\t<div class=\\\"drop-type automatic\\\">\\n\\t\\t\\t<div class=\\\"msg\\\">\\n\\t\\t\\t\\t<h2>\\n\\t\\t\\t\\t\\tWeb Safe\\n\\t\\t\\t\\t<\\/h2>\\n\\t\\t\\t\\t<p>\\n\\t\\t\\t\\t\\tWe'll rename the files so they fit better with the web and create multiple formats images.\\n\\t\\t\\t\\t<\\/p>\\n\\t\\t\\t<\\/div>\\n\\t\\t<\\/div>\\n\\t\\t<div class=\\\"drop-type literal\\\">\\n\\t\\t\\t<div class=\\\"msg\\\">\\n\\t\\t\\t\\t<h2>\\n\\t\\t\\t\\t\\tJust Do It\\n\\t\\t\\t\\t<\\/h2>\\n\\t\\t\\t\\t<p>\\n\\t\\t\\t\\t\\tWe won't mess the files at all, just upload them.\\n\\t\\t\\t\\t<\\/p>\\n\\t\\t\\t<\\/div>\\n\\t\\t<\\/div>\\n\\n\\t<\\/div>\\n\\t<div class=\\\"hidden-elements\\\">\\n\\t\\t<input name=\\\"fileUpload\\\" type=\\\"file\\\" placeholder=\\\"Upload a file\\\" \\/>\\n\\t\\t\\n\\t<\\/div>\\n\\n<\\/div>\"}; \n","export default { name: \"webhandle-tree-image-browser/variant-choice-box\", content: \"<div class=\\\"variant-choice-box\\\">\\n\\t<div class=\\\"img\\\">\\n\\t\\t__!this.thumbnail??'<span class=\\\"material-icons thumbnail-icon\\\">' + thumbnailIcon + '<\\/span>'__\\n\\t\\t__this.thumbnail??'<img loading=\\\"lazy\\\" class=\\\"thumbnail-image\\\" src=\\\"' + safeThumbnail + '\\\" \\/>'__\\n\\t<\\/div>\\n\\t<div class=\\\"size-line\\\">\\n\\t\\t__size__\\n\\t<\\/div>\\n\\t<div class=\\\"bottom\\\">\\n\\t\\t<div class=\\\"content\\\">\\n\\t\\t\\t<div class=\\\"basename\\\">\\n\\t\\t\\t\\t__safeBaseName__\\n\\t\\t\\t<\\/div>\\n\\t\\t\\t<div class=\\\"extensions\\\">\\n\\t\\t\\t\\t__extensions::.\\/extension-pill__\\n\\t\\t\\t<\\/div>\\n\\t\\t<\\/div>\\n\\t\\t<div class=\\\"actions\\\">\\n\\t\\t\\t<button class=\\\"details\\\">\\n\\t\\t\\t\\t<span class=\\\"material-icons\\\">more_vert<\\/span>\\n\\t\\t\\t<\\/button>\\n\\t\\t<\\/div>\\n\\t<\\/div>\\n\\n<\\/div>\"}; \n","export default { name: \"webhandle-tree-image-browser/extension-pill\", content: \"<span class=\\\"extension-pill\\\">__this__<\\/span>\"}; \n","export default { name: \"webhandle-tree-image-browser/guilded-image-upload-form\", content: \"<div class=\\\"guided-image-upload-form ei-form\\\">\\n\\t<label>\\n\\t\\tSource file name:<br>\\n\\t\\t__nativeName__\\n\\t<\\/label>\\n\\t<label>\\n\\t\\tNative resolution:<br>\\n\\t\\t__stats.width__ x __stats.height__\\n\\t<\\/label>\\n\\t<label>\\n\\t\\tAfter uploaded name (no extension):\\n\\t\\t<input name=\\\"name\\\" type=\\\"text\\\" \\/>\\n\\t<\\/label>\\n\\t<div class=\\\"radio-options\\\">\\n\\t\\tOutput format:\\n\\t\\t<label>\\n\\t\\t\\t<input type=\\\"radio\\\" name=\\\"outputFormat\\\" value=\\\"image\\/png\\\" \\/> <span class=\\\"extension-pill\\\">PNG<\\/span>\\n\\t\\t<\\/label>\\n\\t\\t<label>\\n\\t\\t\\t<input type=\\\"radio\\\" name=\\\"outputFormat\\\" value=\\\"image\\/jpeg\\\" \\/> <span class=\\\"extension-pill\\\">JPG<\\/span>\\n\\t\\t<\\/label>\\n\\t<\\/div>\\n\\t<label>\\n\\t\\tOn screen width (px):\\n\\t\\t<input name=\\\"width\\\" type=\\\"number\\\" \\/>\\n\\t<\\/label>\\n\\t<label>\\n\\t\\tOutput quality (0 to 1):\\n\\t\\t<input name=\\\"quality\\\" value=\\\"0.7\\\" type=\\\"number\\\" min=\\\"0\\\" max=\\\"1\\\" step=\\\".01\\\" \\/>\\n\\t<\\/label>\\n\\t\\n\\t<label>\\n\\t\\tAlt text:\\n\\t\\t<textarea name=\\\"altText\\\"><\\/textarea>\\n\\t<\\/label>\\n\\t\\n<\\/div>\"}; \n","export default { name: \"webhandle-tree-image-browser/guilded-file-upload-form\", content: \"<div class=\\\"guided-image-upload-form ei-form\\\">\\n\\t<label>\\n\\t\\tSource file name:<br>\\n\\t\\t__nativeName__\\n\\t<\\/label>\\n\\t<label>\\n\\t\\tAfter uploaded name (with extension):\\n\\t\\t<input name=\\\"name\\\" type=\\\"text\\\" \\/>\\n\\t<\\/label>\\n\\t\\n<\\/div>\"}; \n","\nexport default function formatBytes(bytes, decimals) {\n\tif (bytes == 0)\n\t\treturn '0 Bytes'\n\tvar k = 1024,\n\t\tdm = decimals || 2,\n\t\tsizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],\n\t\ti = Math.floor(Math.log(bytes) / Math.log(k))\n\treturn parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]\n}","import areStylesLoaded from \"./styles-loaded.mjs\";\nimport {loadMaterialIcons} from \"@webhandle/material-icons\"\n\nexport default function loadStyles() {\n\tif(!areStylesLoaded()) {\n\t\tlet link = document.createElement('link')\n\t\tlink.href = '/@webhandle/tree-file-browser/files/css/tree-browser.css'\n\t\tlink.rel = 'stylesheet'\n\t\tdocument.head.appendChild(link)\n\t\t\n\t}\n\tloadMaterialIcons()\n\n}","\n/**\n * Returns true if the styles for the image browser have been loaded\n */\nexport default function areStylesLoaded() {\n\tlet d = document.createElement('div')\n\td.classList.add('webhandle-file-tree-image-browser-test')\n\t\n\td.style.position = 'absolute'\n\td.style.left = '-10000px'\n\t\n\t\n\tdocument.body.appendChild(d)\n\tlet color = window.getComputedStyle(d)['background-color'] \n\td.remove()\n\n\treturn color === 'rgb(101, 105, 99)'\n}","\nexport default class Streamish {\n\tconstructor() {\n\t\tthis.handles = {}\n\t}\n\n\ton(evt, handle) {\n\t\tlet handles = this.handles[evt]\n\t\tif (!handles) {\n\t\t\thandles = this.handles[evt] = []\n\t\t}\n\t\thandles.push(handle)\n\t\treturn this\n\t}\n\n\temit(evt, ...args) {\n\t\tif (evt in this.handles) {\n\t\t\tfor (let handle of this.handles[evt]) {\n\t\t\t\thandle.apply(this, args)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Removes the specified listener from the listener array for the event named eventName.\n\t * @param {string} eventName The event type name\n\t * @param {function} listener The listener function\n\t */\n\tremoveListener(eventName, listener) {\n\t\tif (eventName in this.handles) {\n\t\t\tthis.handles[eventName] = this.handles[eventName].filter(func => {\n\t\t\t\treturn func !== listener\n\t\t\t})\n\t\t}\n\t}\n}","import Streamish from \"./streamish.mjs\"\n\n/**\n * Add this most basic of the EventEmitter functions (on, emit, removeListener) to the browser's\n * EventTarget functionality.\n * \n * The eventEmitter.emit() method allows an arbitrary set of arguments to be passed to the listener \n * functions. Keep in mind that when an ordinary listener function is called, the standard this \n * keyword is intentionally set to reference the EventEmitter instance to which the listener is attached.\n */\nlet base = typeof EventTarget === 'undefined' ? Streamish : EventTarget\nexport default class EventEmitter extends base {\n\tconstructor(target) {\n\t\tsuper(target)\n\t\tif(target) {\n\t\t\tthis.innerEventTarget = target\n\t\t}\n\t\telse {\n\t\t\tthis.innerEventTarget = this\n\t\t}\n\t}\n\t/**\n\t * Adds the listener function to the end of the listeners array for the event named eventName. No checks \n\t * are made to see if the listener has already been added. Multiple calls passing the same combination \n\t * of eventName and listener will result in the listener being added, and called, multiple times.\n\t * @param {string} eventName The event type name\n\t * @param {*} listener The listener function where has arbitrary arguments\n\t */\n\ton(eventName, listener) {\n\t\tif(this.innerEventTarget.addEventListener) {\n\t\t\tlet nativeListener = (event) => {\n\t\t\t\tlistener.apply(this, event.detail)\n\t\t\t}\n\t\t\tlistener.nativeListener = nativeListener\n\t\t\tthis.innerEventTarget.addEventListener(eventName, nativeListener)\n\t\t}\n\t\telse {\n\t\t\tsuper.on(eventName, listener)\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Synchronously calls each of the listeners registered for the event named eventName, in the order \n\t * they were registered, passing the supplied arguments to each.\n\t * \n\t * @param {string} eventName The event type name\n\t * @param {...any} args \n\t */\n\temit(eventName, ...args) {\n\t\tif(this.innerEventTarget.dispatchEvent) {\n\t\t\tthis.innerEventTarget.dispatchEvent(this._makeEvent(eventName, args))\n\t\t}\n\t\telse {\n\t\t\tsuper.emit(eventName, ...args)\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Removes the specified listener from the listener array for the event named eventName.\n\t * @param {string} eventName The event type name\n\t * @param {function} listener The listener function\n\t */\n\tremoveListener(eventName, listener) {\n\t\tif(this.innerEventTarget.removeEventListener) {\n\t\t\tlistener = listener.nativeListener || listener\n\t\t\tthis.innerEventTarget.removeEventListener(eventName, listener)\n\t\t}\n\t\telse {\n\t\t\tsuper.removeListener(eventName, listener)\n\t\t}\n\t\treturn this\n\t}\n\t\n\t_makeEvent(eventName, args) {\n\t\tif(typeof CustomEvent === 'function') {\n\t\t\treturn new CustomEvent(eventName, {\n\t\t\t\tdetail: args\n\t\t\t})\n\t\t}\n\t\telse {\n\t\t\tlet evt = new Event(eventName)\n\t\t\tevt.detail = args\n\t\t\treturn evt\n\t\t}\n\t}\n}","let Emitter\nimport Streamish from \"./streamish.mjs\"\nimport EventEmitter from \"./event-emitter.mjs\"\n\nif (typeof EventTarget !== 'undefined') {\n\tEmitter = EventEmitter\n}\nelse {\n\tEmitter = Streamish\n}\n\n\nexport default Emitter","import { FormAnswerDialog } from \"@webhandle/dialog\"\n\nexport async function deleteFile(evt, selected) {\n\tlet sel = this.getSelectedFiles()\n\n\tif (sel.files.length > 0) {\n\n\t\tlet files = sel.files\n\t\tlet names = sel.names\n\n\t\tif (!this.deleteWithoutConfirm) {\n\t\t\tlet dialog = new FormAnswerDialog({\n\t\t\t\ttitle: 'Delete File' + (files.length > 1 ? 's' : '')\n\t\t\t\t, body: '<p>' + names.join(', ') + '</p>'\n\t\t\t})\n\t\t\tlet prom = dialog.open()\n\t\t\tlet ans = await prom\n\t\t\tif (!ans) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tfor (let file of files) {\n\t\t\tlet path = file.relPath\n\t\t\tlet note\n\t\t\tif (this.eventNotificationPanel) {\n\t\t\t\tnote = this.eventNotificationPanel.addNotification({\n\t\t\t\t\tmodel: {\n\t\t\t\t\t\tstatus: 'pending',\n\t\t\t\t\t\theadline: `deleting ${file.name}`\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t\tawait this.sink.rm(path)\n\t\t\tif (this.eventNotificationPanel) {\n\t\t\t\tnote.remove()\n\t\t\t\tnote = this.eventNotificationPanel.addNotification({\n\t\t\t\t\tmodel: {\n\t\t\t\t\t\tstatus: 'success',\n\t\t\t\t\t\theadline: `removed ${file.name}`\n\t\t\t\t\t}\n\t\t\t\t\t, ttl: 2000\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tfor (let item of sel.boxes) {\n\t\t\titem.remove()\n\t\t}\n\t}\n\tthis.emitter.emit('delete', {\n\t\ttype: 'delete'\n\t\t, selected: sel\n\t})\n}\n\nexport async function deleteDirectory(evt, selected) {\n\tlet path = this.currentNode.file.relPath\n\tlet name = this.currentNode.file.name\n\n\tif (!path) {\n\t\t// probably the root, just cancel\n\t\treturn\n\t}\n\n\tlet dialog = new FormAnswerDialog({\n\t\ttitle: 'Delete Directory'\n\t\t, body: '<p>' + name + '</p>'\n\t})\n\tlet prom = dialog.open()\n\tlet ans = await prom\n\tif (!ans) {\n\t\treturn\n\t}\n\tlet note\n\tif (this.eventNotificationPanel) {\n\t\tnote = this.eventNotificationPanel.addNotification({\n\t\t\tmodel: {\n\t\t\t\tstatus: 'pending',\n\t\t\t\theadline: `deleting ${name}`\n\t\t\t}\n\t\t})\n\t}\n\tawait this.sink.rm(path, { recursive: true })\n\tlet curSelected = this.tree.selected()\n\tlet parent = this.tree.parent(curSelected)\n\n\tthis.tree.removeNode(curSelected)\n\tthis.tree.select(parent.id)\n\n\tif (this.eventNotificationPanel) {\n\t\tnote.remove()\n\t\tnote = this.eventNotificationPanel.addNotification({\n\t\t\tmodel: {\n\t\t\t\tstatus: 'success',\n\t\t\t\theadline: `removed ${name}`\n\t\t\t}\n\t\t\t, ttl: 2000\n\t\t})\n\t}\n}\n","\nexport function _join(...parts) {\n\tparts = parts.filter(part => !!part)\n\tlet path = parts.join('/')\n\treturn path\n}\n\nexport function _determineParentPath(path) {\n\tif(!path) {\n\t\treturn ''\n\t}\n\tlet parts = path.split('/')\n\tparts.pop()\n\treturn parts.join('/')\n}\n\nexport function _fileToKalpaNode(file) {\n\tlet node = {\n\t\tid: this.idInd++\n\t\t, label: file.name\n\t\t, directory: file.directory\n\t\t, file: file\n\t\t, loaded: false\n\t}\n\n\tlet parent = this.nodes[this._determineParentPath(file.relPath)]\n\tthis.nodes[file.relPath] = node\n\n\tif (parent) {\n\t\tnode.parentId = parent.id\n\t\tnode.path = file.relPath\n\t}\n\n\tfile.path = node.path\n\treturn node\n}\n\nexport function _determineExtensions(variant) {\n\tlet extensions = new Set()\n\tif (variant.variants) {\n\t\tfor (let imgVariant of variant.variants) {\n\t\t\textensions.add(imgVariant.ext)\n\t\t}\n\t}\n\telse {\n\t\textensions.add(variant.ext)\n\t}\n\n\tlet result = Array.from(extensions).filter(item => !!item)\n\tresult.sort((a, b) => {\n\t\treturn a.toLowerCase().localeCompare(b.toLowerCase())\n\t})\n\n\treturn result\n}\n\nexport function _determineSizes(variant) {\n\tlet min = 2000000000\n\tlet max = 0\n\tif (variant.variants) {\n\t\tfor (let imgVariant of variant.variants) {\n\t\t\tlet size = imgVariant.file.stat.size\n\t\t\tif (size > max) {\n\t\t\t\tmax = size\n\t\t\t}\n\t\t\tif (size < min) {\n\t\t\t\tmin = size\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tlet size = variant.file.stat.size\n\t\tif (size > max) {\n\t\t\tmax = size\n\t\t}\n\t\tif (size < min) {\n\t\t\tmin = size\n\t\t}\n\t}\n\treturn [min, max]\n}\n\nexport function _sortFiles(files) {\n\tfiles.sort((one, two) => {\n\t\treturn one.relPath.toLowerCase().localeCompare(two.relPath.toLowerCase())\n\t})\n\n\treturn files\n}\n\nexport function _compareVariants(one, two) {\n\treturn one.baseName.toLowerCase().localeCompare(two.baseName.toLowerCase())\n}\n\nexport function sanitizeFileName(name) {\n\treturn name.split('/').join('-').split('..').join('-')\n}\n\n\nexport function _isImageFile(file) {\n\tif (!file.type.startsWith('image')) {\n\t\treturn false\n\t}\n\tif (file.type.includes('jpeg') || file.type.includes('png') || file.type.includes('webp')) {\n\t\treturn true\n\t}\n\treturn false\n}\n\nexport function setIfNotSet(key, value) {\n\tif (!(key in this)) {\n\t\tthis[key] = value\n\t}\n}\n\nexport function _addPending(file) {\n\tlet note\n\tif (this.eventNotificationPanel) {\n\t\tnote = this.eventNotificationPanel.addNotification({\n\t\t\tmodel: {\n\t\t\t\tstatus: 'pending',\n\t\t\t\theadline: `uploading ${file.name}`\n\t\t\t}\n\t\t})\n\t}\n\treturn note\n}\n","import { Dialog } from '@webhandle/dialog'\nimport escapeHtmlAttributeValue from '@dankolz/escape-html-attribute-value'\n\nexport function changeFilesView(evt, selected) {\n\tlet className = selected.getAttribute('data-show-class')\n\tthis.changeFilesViewToClass(className)\n}\n\nexport function changeFilesViewToClass(className) {\n\tlet choiceBoxes = this.el.querySelector('.choice-boxes')\n\tlet classes = [...this.el.querySelector('.view-icons').querySelectorAll('button')].map(button => button.getAttribute('data-show-class'))\n\tclasses.forEach(item => {\n\t\tchoiceBoxes.classList.remove(item)\n\t})\n\tchoiceBoxes.classList.add(className)\n}\n\nexport function applyFilter(evt, selected) {\n\tsetTimeout(() => {\n\t\tlet value = this.el.querySelector('[name=\"filter\"]').value\n\t\tlet allVariants = this.el.querySelectorAll('.choice-boxes .variant-choice-box')\n\t\tfor (let variant of allVariants) {\n\t\t\tvariant.classList.remove('hidden')\n\t\t\tif (value) {\n\t\t\t\tvalue = value.toLowerCase()\n\t\t\t\tlet searchString = variant.variant.baseName.toLowerCase() + variant.variant.extensions.map(ext => ext.toLowerCase()).join()\n\t\t\t\tif (searchString.indexOf(value) < 0) {\n\t\t\t\t\tvariant.classList.add('hidden')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.setFolderInfo()\n\t})\n}\n\nexport function clearFilter(evt, selected) {\n\tthis.el.querySelector('[name=\"filter\"]').value = ''\n\tthis.applyFilter()\n}\n\nexport function selectVariant(evt, selected) {\n\tlet currentSelected = this.el.querySelectorAll('.choice-boxes .variant-choice-box.selected')\n\tif (!evt.ctrlKey && !evt.shiftKey) {\n\t\tfor (let sel of currentSelected) {\n\t\t\tsel.classList.remove('selected')\n\t\t}\n\t}\n\n\tif (evt.shiftKey) {\n\t\tlet cur = selected\n\t\tdo {\n\t\t\tif (cur.classList.contains('selected')) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcur.classList.add('selected')\n\t\t\tcur = cur.previousElementSibling\n\t\t}\n\t\twhile (cur);\n\t}\n\telse {\n\t\tselected.classList.toggle('selected')\n\t}\n\n\n\tlet sel = this.getSelectedFiles()\n\tthis.emitter.emit('select', {\n\t\ttype: 'select'\n\t\t, selected: sel\n\t})\n}\n\n\n\nexport function showVariantDetails(evt, selected) {\n\tlet choiceBox = selected.closest('.variant-choice-box')\n\tlet variant = choiceBox.variant\n\n\tlet files = this._getAssociatedRealFiles(variant)\n\n\tlet content = '<div class=\"variant-details-information\">'\n\tif (variant.safeThumbnail) {\n\t\tcontent += `<div class=\"details-preview-image\">\n\t\t<img loading=\"lazy\" src=\"${variant.safeThumbnail}\" />\n\t\t</div>`\n\t}\n\n\tcontent += '<ul class=\"variants\">'\n\tfor (let file of files) {\n\t\tcontent += '<li><a target=\"_blank\" href=\"' + escapeHtmlAttributeValue(this.escapeAccessUrl(file.accessUrl)) + '\">'\n\t\tcontent += escapeHtmlAttributeValue(file.name) + '</a> - ' + this._formatBytes(file.stat.size)\n\t\tcontent += '</li>'\n\t}\n\tcontent += '</ul>'\n\n\tcontent += '</div>'\n\n\tlet dialog = new Dialog({\n\t\ttitle: 'File Details: ' + variant.baseName\n\t\t, body: content\n\t\t, showCancelButton: false\n\t})\n\tlet prom = dialog.open()\n\tprom.then(async data => {\n\t\tif (data) {\n\t\t}\n\t})\n}\n\nexport function setFolderInfo() {\n\tlet fileCount = 0\n\tlet variantCount = 0\n\tlet byteCount = 0\n\tlet nonImages = 0\n\tlet allVariants = this.el.querySelectorAll('.choice-boxes .variant-choice-box')\n\tfor (let variant of allVariants) {\n\t\tif (variant.classList.contains('hidden')) {\n\t\t\tcontinue\n\t\t}\n\t\tvariantCount++\n\n\t\tif (variant.variant.variants) {\n\t\t\tvariant.variant.variants.forEach(variant => {\n\t\t\t\tfileCount++\n\t\t\t\tbyteCount += variant.file.stat.size\n\t\t\t})\n\n\t\t}\n\t\telse {\n\t\t\tfileCount++\n\t\t\tbyteCount += variant.variant.file.stat.size\n\t\t\tnonImages++\n\t\t}\n\t}\n\tthis.el.querySelector('.folder-info').innerHTML = `${variantCount} items / ${fileCount} files / ${this._formatBytes(byteCount)} `\n\tif (variantCount > this.listTriggerSize) {\n\t\tthis.changeFilesViewToClass('list-text')\n\t}\n\tthis.el.querySelector('.view-icons').classList.remove('no-img')\n\tif (variantCount - nonImages > this.listLockSize) {\n\t\tthis.el.querySelector('.view-icons').classList.add('no-img')\n\t}\n}\n\nexport function cleanFileInfo() {\n\tthis.el.querySelector('.folder-info').innerHTML = ''\n\tlet choicesBoxes = this.el.querySelector('.choice-boxes')\n\tchoicesBoxes.innerHTML = '<div class=\"loading-info\">Loading Information Now</div>'\n\tthis.el.querySelector('.view-icons').classList.add('no-img')\n}\n","\nexport function getDropCoverSelector() {\n\treturn '.img-drop-cover'\n}\n\nexport async function handleDrop(evt, selected) {\n\tlet uploadType = 'literal'\n\tlet dropSquare = evt.target.closest('.drop-type')\n\tif (dropSquare) {\n\t\tif (dropSquare.classList.contains('guided-upload')) {\n\t\t\tuploadType = 'guided'\n\t\t}\n\t\telse if (dropSquare.classList.contains('automatic')) {\n\t\t\tuploadType = 'automatic'\n\t\t}\n\t}\n\n\tthis._cleanupDropDone()\n\tevt.preventDefault()\n\tlet files = await this._getFilesFromEvent(evt)\n\tthis.uploadFiles(files, { uploadType })\n}\n\nexport function isFileTypeDrag(evt) {\n\tlet fileType = true\n\tif (evt.dataTransfer) {\n\t\tif (evt.dataTransfer.items[0].kind === 'string') {\n\t\t\tfileType = false\n\t\t}\n\t}\n\n\treturn fileType\n}\n\nexport function dragEnter(evt, selected) {\n\tlet overlay = this.isFileTypeDrag(evt)\n\tif (overlay) {\n\t\tthis.overCount++\n\t\tthis.el.querySelector(this.getDropCoverSelector()).classList.add('file-dropping')\n\t}\n}\nexport function dragLeave(evt, selected) {\n\tif (this.isFileTypeDrag(evt)) {\n\t\tthis.overCount--\n\t\tif (this.overCount == 0) {\n\t\t\tthis._cleanupDropDone()\n\t\t}\n\t}\n}\nexport function dragOver(evt, selected) {\n\tevt.preventDefault()\n}\n\nexport function _cleanupDropDone() {\n\tthis.overCount = 0;\n\t[...this.el.querySelectorAll('.file-dropping')].forEach(cover => cover.classList.remove('file-dropping'))\n}\n\nexport async function handlePaste(evt) {\n\tif (this.ignoreGlobalEvents) {\n\t\treturn\n\t}\n\tif (evt.clipboardData && evt.clipboardData.files && evt.clipboardData.files.length > 0) {\n\t\tevt.preventDefault()\n\t\tthis.uploadFiles(evt.clipboardData.files, { uploadType: 'guided' })\n\t}\n}","import { FormAnswerDialog } from \"@webhandle/dialog\"\n\nexport function createDirectory(evt, selected) {\n\tlet dialog = new FormAnswerDialog({\n\t\ttitle: 'Create Directory'\n\t\t, body: '<label>Directory name <input type=\"text\" name=\"name\" /></label>'\n\t})\n\tlet prom = dialog.open()\n\tprom.then(async data => {\n\t\tif (data) {\n\t\t\tlet directoryPath = this.currentNode.file.relPath + '/' + data.name\n\t\t\tawait this.sink.mkdir(directoryPath)\n\t\t\tlet file = await this.sink.getFullFileInfo(directoryPath)\n\t\t\tlet node = this._fileToKalpaNode(file)\n\t\t\tthis.tree.options.stream.emit('data', node)\n\t\t\tlet cur = this.tree.selected()\n\t\t\tif (cur) {\n\t\t\t\tthis.tree.expand(cur.id)\n\t\t\t}\n\t\t}\n\t})\n\n}","\nfunction breakOnChars(chrs, txt) {\n\tfor (let c of chrs) {\n\t\ttxt = txt.split(c).join('<wbr>' + c)\n\t}\n\treturn txt\n}\n\nexport default function addSoftBreaks(txt) {\n\tif(!txt || typeof txt !== 'string') {\n\t\treturn txt\n\t}\n\t\n\tlet chars = [...txt]\n\ttxt = ''\n\tfor(let i = 0; i < chars.length; i++) {\n\t\ttxt += chars[i]\n\t\tif(i % 10 === 0) {\n\t\t\ttxt += '<wbr>'\n\t\t}\n\t}\n\ttxt = breakOnChars(['_'], txt)\n\n\treturn txt\n}","import condense from '@dankolz/webp-detection/lib/condense-image-variants.js'\nimport escapeHtmlAttributeValue from '@dankolz/escape-html-attribute-value'\nimport addSoftBreaks from '../add-soft-breaks.mjs'\n\nexport function createVariantValues(info) {\n\tlet variants = condense(info.children)\n\tlet variantValues = Object.values(variants)\n\n\tlet used = []\n\tfor (let variant of variantValues) {\n\t\tused.push(...this._getAssociatedRealFiles(variant).map(variant => variant.name))\n\t}\n\n\tlet remainingChildren = info.children.filter(item => {\n\t\treturn !used.includes(item.name)\n\t})\n\t\t.filter(item => !item.directory)\n\n\t// Add thumbnails\n\tfor (let child of variantValues) {\n\t\tchild.thumbnailIcon = 'image'\n\t\tif (child.preview) {\n\t\t\tchild.thumbnail = this._createAccessUrl(child.preview.file)\n\t\t\tchild.safeThumbnail = escapeHtmlAttributeValue(child.thumbnail)\n\t\t}\n\t}\n\n\tif (!this.imagesOnly) {\n\t\tfor (let file of remainingChildren) {\n\t\t\tlet info = {\n\t\t\t\tfile: file\n\t\t\t\t, thumbnailIcon: 'description'\n\t\t\t}\n\t\t\tlet name = file.name\n\t\t\tinfo.ext = name.substring(name.lastIndexOf('.') + 1)\n\t\t\tinfo.baseName = name.substring(0, name.lastIndexOf('.'))\n\t\t\tvariantValues.push(info)\n\t\t}\n\t}\n\n\n\t// Determine extensions, add additional top level info (safeBaseName)\n\tfor (let item of variantValues) {\n\t\titem.extensions = this._determineExtensions(item)\n\t\titem.sizes = this._determineSizes(item)\n\t\tif (item.sizes[0] == item.sizes[1]) {\n\t\t\titem.size = this._formatBytes(item.sizes[0])\n\t\t}\n\t\telse {\n\t\t\titem.size = this._formatBytes(item.sizes[0]) + ' - ' + this._formatBytes(item.sizes[1])\n\t\t}\n\t\titem.safeBaseName = addSoftBreaks(escapeHtmlAttributeValue(item.baseName))\n\t}\n\n\tvariantValues.sort(this._compareVariants)\n\treturn variantValues\n}\n\nexport async function _getFilesFromEvent(evt) {\n\tlet files = []\n\n\t// items is the new interface we should use if that's available\n\tif (evt.dataTransfer.items) {\n\t\tlet foundItems = [];\n\t\t[...evt.dataTransfer.items].forEach((item, i) => {\n\t\t\tfoundItems.push(item)\n\t\t})\n\t\tfor (let item of foundItems) {\n\t\t\tif (item.kind === \"file\") {\n\t\t\t\tif (item.webkitGetAsEntry) {\n\t\t\t\t\tlet entry = item.webkitGetAsEntry()\n\t\t\t\t\tif (entry) {\n\t\t\t\t\t\t// if there's no entry, it's probably not a file, so we'll just ignore\n\t\t\t\t\t\tif (entry.isDirectory) {\n\t\t\t\t\t\t\tcontinue\n\n\t\t\t\t\t\t\t// Evenually we'll want to handle directories too, but for now we'll just go\n\t\t\t\t\t\t\t// on with the other items\n\n\t\t\t\t\t\t\t// var dirReader = entry.createReader()\n\t\t\t\t\t\t\t// dirReader.readEntries(function (entries) {\n\t\t\t\t\t\t\t// \tconsole.log(entries)\n\t\t\t\t\t\t\t// })\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tfiles.push(item.getAsFile())\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfiles.push(item.getAsFile())\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (item instanceof File) {\n\t\t\t\t// Maybe from a file input element\n\t\t\t\tfiles.push(item)\n\t\t\t}\n\t\t}\n\t} else {\n\t\t[...evt.dataTransfer.files].forEach((file, i) => {\n\t\t\tfiles.push(file)\n\t\t})\n\t}\n\treturn files\n}\n\nexport function _getAssociatedRealFiles(variant) {\n\tlet files = []\n\tif (variant.variants) {\n\t\tfiles.push(...variant.variants.map(variant => variant.file))\n\t}\n\telse {\n\t\tfiles.push(variant.file)\n\t}\n\tif (variant.definitionFile) {\n\t\tfiles.push(variant.definitionFile)\n\t}\n\n\treturn files\n}\n\nexport function _createAccessUrl(file) {\n\treturn this.escapeAccessUrl(file.accessUrl)\n}\n\nfunction urlEscapeChars(chrs, url) {\n\tfor (let c of chrs) {\n\t\turl = url.split(c).join(encodeURIComponent(c))\n\t}\n\treturn url\n}\n\nexport function escapeAccessUrl(url) {\n\treturn urlEscapeChars(['%', ' ', '#', '?', '<', '>', '$', '@', '^', '&'], url)\n}\n\n\nexport function getSelectedFiles() {\n\tlet result = {\n\t\tboxes: []\n\t\t, variants: []\n\t\t, files: []\n\t\t, names: []\n\t}\n\tlet currentSelected = this.el.querySelectorAll('.choice-boxes .variant-choice-box.selected')\n\tif (currentSelected.length > 0) {\n\t\tfor (let sel of currentSelected) {\n\t\t\tresult.boxes.push(sel)\n\t\t\tresult.variants.push(sel.variant)\n\t\t\tresult.files.push(...this._getAssociatedRealFiles(sel.variant))\n\t\t}\n\t\tlet names = result.files.map(file => file.name)\n\t\tresult.names.push(...names)\n\t}\n\n\treturn result\n}\n\nexport function _transformRelativeUrlToPublic(url) {\n\tif(url.startsWith('/') == false) {\n\t\turl = '/' + url\n\t}\n\treturn url\t\n}\n\nexport async function getSelectedUrl(selectedFiles) {\n\tif(!selectedFiles) {\n\t\tselectedFiles = this.getSelectedFiles()\n\t}\n\t\n\tif(selectedFiles.variants.length == 0) {\n\t\treturn\n\t}\n\t\n\tlet variant = selectedFiles.variants[0]\n\tlet chosen\n\tif(variant.primary) {\n\t\tchosen = variant.primary.file\n\t}\n\telse {\n\t\tchosen = variant.file\n\t}\n\t\n\tlet base = this._transformRelativeUrlToPublic(chosen.relPath)\n\t\n\tif(variant.definitionFile) {\n\t\tlet defData = await this.sink.read(variant.definitionFile.relPath)\n\t\ttry {\n\t\t\tlet data = JSON.parse(defData)\n\t\t\tbase += this.getSelectedUrlExtFromMeta(data)\n\t\t}\n\t\tcatch(e) {\n\n\t\t}\n\t}\n\t\n\treturn base\n\n}\n\nexport function getSelectedUrlExtFromMeta(data) {\n\tlet url = ''\n\tlet sizes = data.displaySize.split('x')\n\turl += `#format=webp2x&width=${sizes[0]}&height=${sizes[1]}`\n\t\n\tif(data.altText) {\n\t\turl += '&alt=' + encodeURIComponent(data.altText)\n\t}\n\t\n\treturn url\n}\n","\n/**\n * \n * @param {File,string} file \n */\nexport default function baseImageName(file) {\n\tlet name\n\tif(typeof file === 'string') {\n\t\tname = file\n\t}\n\telse if(file instanceof File) {\n\t\tname = file.name\n\t}\n\t\n\tlet parts = name.split('.')\n\t\n\tif(parts.length > 1) {\n\t\tparts.pop()\n\t}\n\tname = parts.join('.')\n\tname = name.replace(/-@2x$/, '')\n\tname = name.replace(/@2x$/, '')\n\tname = name.replace(/-2x$/, '')\n\tname = name.replace(/2x$/, '')\n\n\tlet chars = [name.substring(0, 1)]\n\tfor(let char of name.substring(1)) {\n\t\tif(char.match(/[A-Z]/)) {\n\t\t\tchars.push('-')\n\t\t}\n\t\tchars.push(char)\n\t}\n\tname = chars.join('')\n\n\tname = name.toLowerCase()\n\tname = name.replace(/[^1234567890a-z-]/g, '-')\n\tname = name.replace(/--+/g, '-')\n\t\n\n\treturn name\n}","\n/**\n * Takes data, perhaps even an image, and resolves to a fully \n * loaded image.\n * @param {Blob,ArrayBuffer,string,Image} data \n */\nexport default async function dataToImage(data) {\n\treturn new Promise((resolve, reject) => {\n\t\tlet finalImage\n\t\tlet objectUrl\n\t\tif (data instanceof Image) {\n\t\t\tfinalImage = data\n\t\t}\n\t\telse if (typeof data === 'string') {\n\t\t\tfinalImage = new Image();\n\t\t\tfinalImage.src = data;\n\t\t}\n\t\t// ArrayBuffer.isView(data) might be true or could be a Blob or File\n\t\telse {\n\t\t\t// let's make a blob first. This works if it's an ArrayBuffer of a Blob\n\t\t\tlet imageBlob = new Blob([data])\n\t\t\tobjectUrl = URL.createObjectURL(imageBlob)\n\n\t\t\tfinalImage = new Image()\n\t\t\tfinalImage.src = objectUrl\n\t\t}\n\n\t\tfunction finish() {\n\t\t\tif (objectUrl) {\n\t\t\t\tURL.revokeObjectURL(objectUrl)\n\t\t\t}\n\t\t\tresolve(finalImage)\n\t\t}\n\t\tif (finalImage.complete) {\n\t\t\tfinish()\n\t\t}\n\t\telse {\n\t\t\t// we'll have to wait till it's loaded\n\t\t\tfinalImage.addEventListener('load', () => {\n\t\t\t\tfinish()\n\t\t\t})\n\t\t}\n\t})\n\n}","import dataToImage from \"./data-to-image.mjs\"\n\n/*image, base64 encoded data of image, blob, file, or arraybuffer */\nexport default async function resizeImage(imageData,\n\t{ maxWidth = 1920, quality = .7, outputFormat = \"image/png\" } = {}) {\n\treturn new Promise(async (resolve, reject) => {\n\n\t\ttry {\n\t\t\tlet resizeImg = await dataToImage(imageData)\n\t\t\tlet ratio = resizeImg.naturalWidth / maxWidth\n\t\t\tlet maxHeight = resizeImg.naturalHeight / ratio\n\n\t\t\tvar resizeCanvas = document.createElement('canvas');\n\t\t\tresizeCanvas.width = maxWidth;\n\t\t\tresizeCanvas.height = maxHeight;\n\n\t\t\tvar ctx = resizeCanvas.getContext('2d');\n\t\t\tctx.clearRect(0, 0, resizeCanvas.width, resizeCanvas.height);\n\t\t\tctx.drawImage(resizeImg, 0, 0, resizeCanvas.width, resizeCanvas.height);\n\n\n\t\t\tresizeCanvas.toBlob((blob) => {\n\t\t\t\tresolve(blob)\n\t\t\t}, outputFormat, quality);\n\t\t} catch (e) {\n\t\t\tif (console && console.log) {\n\t\t\t\tconsole.log('error resizing image: ' + e);\n\t\t\t}\n\t\t\treject(e)\n\t\t}\n\t})\n}\n","import dataToImage from \"./data-to-image.mjs\";\n\nexport default async function getImageStats(data) {\n\tlet img = await dataToImage(data)\n\treturn {\n\t\twidth: img.naturalWidth\n\t\t, height: img.naturalHeight\n\n\t}\n\n}","\nlet types = {\n\t\"image/png\": \"png\"\n\t, \"image/jpeg\": \"jpg\"\n\t, \"image/jpg\": \"jpg\"\n\t, \"image/webp\": \"webp\"\n}\n\n\nexport default function getExtension(mime) {\n\tif (mime in types) {\n\t\treturn types[mime]\n\t}\n\n\tlet ext = mime.split('/').pop()\n\treturn ext\n}\n","import resizeImage from '../client-lib/image-resize.mjs'\nimport dataToImage from '../client-lib/data-to-image.mjs'\nimport getImageStats from '../client-lib/get-image-stats.mjs'\nimport getExtension from './get-extension-from-mime.mjs'\n\nlet webpMime = 'image/webp'\n\nexport default async function makeImageSet(data,\n\t{ \n\t\tsingleDensityWidth = null\n\t\t, quality = .7\n\t\t, outputFormat = \"image/png\"\n\t\t, doubleDensityInput = true\n\t\t, baseFileName \n\t\t, altText\t\t\n\t} = {}\n) {\n\tlet source = await dataToImage(data)\n\tlet stats = await getImageStats(source)\n\tlet ratio = stats.width / stats.height\n\n\tif (!baseFileName) {\n\t\tbaseFileName = \"\" + (new Date().getTime())\n\t}\n\tif (!singleDensityWidth) {\n\t\tif (doubleDensityInput) {\n\t\t\tsingleDensityWidth = stats.width / 2\n\t\t}\n\t\telse {\n\t\t\tsingleDensityWidth = stats.width\n\t\t}\n\t}\n\tlet doubleDensityWidth = singleDensityWidth * 2\n\n\tlet suffixes = {\n\t\t'-2x': doubleDensityWidth\n\t\t, '': singleDensityWidth\n\t\t, '-half': Math.floor(singleDensityWidth / 2)\n\t\t, '-quarter': Math.floor(singleDensityWidth / 4)\n\t}\n\n\tlet files = {}\n\n\tfor (let key of Object.keys(suffixes)) {\n\t\tlet width = suffixes[key]\n\t\tlet data = await resizeImage(source, {\n\t\t\tmaxWidth: width\n\t\t\t, quality: quality\n\t\t\t, outputFormat: outputFormat\n\t\t})\n\t\tfiles[baseFileName + key + '.' + getExtension(outputFormat)] = data\n\n\t\tdata = await resizeImage(source, {\n\t\t\tmaxWidth: width\n\t\t\t, quality: quality\n\t\t\t, outputFormat: webpMime\n\t\t})\n\t\tfiles[baseFileName + key + '.' + getExtension(webpMime)] = data\n\t}\n\n\n\tlet info = {\n\t\t\"name\": baseFileName,\n\t\t\"size\": doubleDensityWidth + \"x\" + (doubleDensityWidth / ratio),\n\t\t\"displaySize\": singleDensityWidth + \"x\" + (singleDensityWidth / ratio),\n\t\t\"fallback\": getExtension(outputFormat),\n\t\t\"altText\": altText || baseFileName\n\t}\n\t\n\t\n\tfiles[baseFileName + '.json'] = JSON.stringify(info, null, '\\t')\n\n\treturn files\n\n}","import baseImageName from \"./base-image-name.mjs\"\n\n/**\n * \n * @param {File,string} file \n */\nexport default function nameParts(file) {\n\tlet name\n\tif(typeof file === 'string') {\n\t\tname = file\n\t}\n\telse if(file instanceof File) {\n\t\tname = file.name\n\t}\n\t\n\tlet result = [baseImageName(name)]\n\t\n\tlet parts = name.split('.')\n\tif(parts.length > 1) {\n\t\tresult.push(parts.pop())\n\t}\n\t\n\treturn result\n}","import { FormAnswerDialog } from '@webhandle/dialog'\nimport baseImageName from '../base-image-name.mjs'\nimport makeImageSet from '../make-image-set.mjs'\nimport nameParts from '../name-parts.mjs'\nimport getFileImageStats from '../get-file-image-stats.mjs'\nimport { guidedImageUploadForm, guidedFileUploadForm } from '../../views/load-browser-views.js'\n\n\nexport async function _uploadGuidedImageFile(file) {\n\tlet baseFileName = baseImageName(file)\n\tlet stats = await getFileImageStats(file)\n\n\tlet data = {\n\t\tnativeName: file.name\n\t\t, name: baseFileName\n\t\t, outputFormat: file.type\n\t\t, stats: stats\n\t\t, width: Math.floor(stats.width / 2)\n\t}\n\n\n\tlet dialog = new FormAnswerDialog({\n\t\ttitle: 'Upload File'\n\t\t, body: guidedImageUploadForm(data)\n\t\t, data: data\n\t\t, className: 'webhandle-file-tree-image-browser'\n\t})\n\tlet prom = dialog.open()\n\tlet result = await prom\n\n\tif (result) {\n\t\tlet makeImageData = {\n\t\t\tbaseFileName: result.name\n\t\t\t, outputFormat: result.outputFormat\n\t\t\t, singleDensityWidth: parseInt(result.width)\n\t\t\t, quality: parseFloat(result.quality)\n\t\t\t, altText: result.altText\n\t\t}\n\n\t\tlet note = this._addPending(file)\n\t\tlet files = await makeImageSet(file, makeImageData)\n\t\tlet meta = JSON.parse(files[makeImageData.baseFileName + '.json'])\n\n\t\tlet mainUrl\n\t\tfor (let fileName of Object.keys(files)) {\n\t\t\tlet path = await this._uploadData(fileName, files[fileName])\n\t\t\tif(fileName === meta.name + '.' + meta.fallback) {\n\t\t\t\tmainUrl = path\n\t\t\t}\n\t\t}\n\n\t\tlet base = this._transformRelativeUrlToPublic(mainUrl)\n\t\t\n\t\tlet ext = this.getSelectedUrlExtFromMeta(meta)\n\t\tbase += ext\n\n\t\tif (note) {\n\t\t\tnote.remove()\n\t\t}\n\n\t\treturn base\n\t}\n}\n\nexport async function _uploadGuidedFile(file) {\n\tlet parts = nameParts(file)\n\n\tlet data = {\n\t\tnativeName: file.name\n\t\t, name: parts.join('.')\n\t}\n\n\n\tlet dialog = new FormAnswerDialog({\n\t\ttitle: 'Upload File'\n\t\t, body: guidedFileUploadForm(data)\n\t\t, data: data\n\t\t, className: 'webhandle-file-tree-image-browser'\n\t})\n\tlet prom = dialog.open()\n\tlet result = await prom\n\n\tif (result) {\n\t\tlet note = this._addPending(file)\n\n\t\tlet mainUrl = await this._uploadData(result.name, file)\n\t\tlet base = this._transformRelativeUrlToPublic(mainUrl)\n\n\t\tif (note) {\n\t\t\tnote.remove()\n\t\t}\n\t\treturn base\n\t}\n}\n\nexport async function _uploadAutomaticImageFile(file) {\n\tlet note = this._addPending(file)\n\tlet parts = nameParts(file)\n\tlet baseFileName = parts[0]\n\n\tlet files = await makeImageSet(file, {\n\t\tbaseFileName: baseFileName,\n\t\toutputFormat: file.type\n\t})\n\tlet meta = JSON.parse(files[baseFileName + '.json'])\n\n\tlet mainUrl\n\tfor (let fileName of Object.keys(files)) {\n\t\tlet path = await this._uploadData(fileName, files[fileName])\n\t\tif(fileName === meta.name + '.' + meta.fallback) {\n\t\t\tmainUrl = path\n\t\t}\n\t}\n\tlet base = this._transformRelativeUrlToPublic(mainUrl)\n\tlet ext = this.getSelectedUrlExtFromMeta(meta)\n\tbase += ext\n\n\tif (note) {\n\t\tnote.remove()\n\t}\n\treturn base\n}\n\nexport async function uploadFiles(files, { uploadType } = {}) {\n\tlet uploadedAccessUrls = []\n\tfor (let file of files) {\n\n\t\tlet uploaded = false\n\t\tif (uploadType === 'guided' && this._isImageFile(file)) {\n\t\t\tuploaded = await this._uploadGuidedImageFile(file)\n\t\t}\n\t\telse if (uploadType === 'guided') {\n\t\t\tuploaded = await this._uploadGuidedFile(file)\n\t\t}\n\t\telse if (uploadType === 'automatic' && this._isImageFile(file)) {\n\t\t\tuploaded = await this._uploadAutomaticImageFile(file)\n\t\t}\n\t\telse {\n\t\t\tlet note = this._addPending(file)\n\t\t\tlet path\n\t\t\tif (uploadType === 'automatic') {\n\t\t\t\tlet parts = nameParts(file)\n\t\t\t\tpath = await this._uploadData(parts.join('.'), file)\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpath = await this._uploadData(file.name, file)\n\t\t\t}\n\t\t\tuploaded = this._transformRelativeUrlToPublic(path)\n\t\t\t\n\t\t\tif (note) {\n\t\t\t\tnote.remove()\n\t\t\t}\n\t\t}\n\t\tif (this.eventNotificationPanel && uploaded) {\n\t\t\tthis.eventNotificationPanel.addNotification({\n\t\t\t\tmodel: {\n\t\t\t\t\tstatus: 'success',\n\t\t\t\t\theadline: `uploaded ${file.name}`\n\t\t\t\t}\n\t\t\t\t, ttl: 2000\n\t\t\t})\n\t\t}\n\t\tuploadedAccessUrls.push(uploaded)\n\t}\n\tthis.setCurrentNode(this.currentNode)\n\tthis.emitter.emit('upload', {\n\t\ttype: 'upload'\n\t\t, accessUrls: uploadedAccessUrls\n\t})\n\treturn uploadedAccessUrls\n}\n\n\nexport function _uploadFileButton(evt, selected) {\n\tthis.el.querySelector(this.fileUploadSelector).click()\n}\n\nexport async function _uploadFile(evt, selected) {\n\tevt.preventDefault()\n\tlet input = this.el.querySelector(this.fileUploadSelector)\n\tevt.dataTransfer = {\n\t\tfiles: input.files\n\t}\n\tlet files = await this._getFilesFromEvent(evt)\n\tif(files.length > 0) {\n\t\tlet result = this.uploadFiles(files, { uploadType: 'guided' })\n\t\tinput.value = ''\n\t\treturn result\n\t}\n}\n","import dataToImage from './data-to-image.mjs'\nimport getImageStats from './get-image-stats.mjs'\nimport getExtension from './get-extension-from-mime.mjs'\n\n/**\n * \n * @param {File} file \n * @returns \n */\nexport default async function getFileImageStats(file) {\n\tlet source = await dataToImage(file)\n\tlet stats = await getImageStats(source)\n\tstats.ratio = stats.width / stats.height\n\tstats.ext = getExtension(file.type)\n\n\treturn stats\n}","\nexport async function _uploadData(name, data) {\n\tlet path = this.currentNode.file.relPath + '/' + this.sanitizeFileName(name)\n\tawait this.sink.write(path, data)\n\treturn path\n}\n\nexport async function findDirectories() {\n\treturn new Promise((resolve, reject) => {\n\t\tlet results = []\n\t\tlet events = this.sink.find({\n\t\t\tfile: false\n\t\t})\n\t\tevents.on('data', (item) => {\n\t\t\tresults.push(item)\n\t\t})\n\t\tevents.on('done', () => {\n\t\t\tresolve(results)\n\t\t})\n\t})\n}","import { View } from '@webhandle/backbone-view'\nimport { imageBrowserFrame, variantChoiceBox } from '../views/load-browser-views.js'\nimport {KalpaTreeView} from \"kalpa-tree-on-page/kalpa-tree-view\"\nimport formatBytes from './format-bytes.mjs'\nimport loadStyles from './load-styles.mjs'\n\nimport Emitter from '@webhandle/minimal-browser-event-emitter'\n\n// method imports\nimport { deleteFile, deleteDirectory } from './image-browser-view-methods/delete.mjs'\nimport {\n\t_join, _determineParentPath, _fileToKalpaNode, _determineExtensions, _addPending,\n\t_determineSizes, _sortFiles, _compareVariants, sanitizeFileName, _isImageFile, setIfNotSet\n} from './image-browser-view-methods/utils.mjs'\nimport { changeFilesView, changeFilesViewToClass, applyFilter, clearFilter, selectVariant, showVariantDetails, setFolderInfo, cleanFileInfo } from './image-browser-view-methods/view-interactions.mjs'\nimport { getDropCoverSelector, handleDrop, isFileTypeDrag, dragEnter, dragLeave, dragOver, _cleanupDropDone, handlePaste } from './image-browser-view-methods/drag-and-drop.mjs'\nimport { createDirectory } from './image-browser-view-methods/create-directory.mjs'\nimport { createVariantValues, _getFilesFromEvent, _getAssociatedRealFiles, _createAccessUrl, escapeAccessUrl,\n\tgetSelectedFiles, _transformRelativeUrlToPublic, getSelectedUrl, getSelectedUrlExtFromMeta } from './image-browser-view-methods/file-obj-manipulation.mjs'\nimport { _uploadGuidedImageFile, _uploadGuidedFile, _uploadAutomaticImageFile, uploadFiles, _uploadFileButton, _uploadFile } from './image-browser-view-methods/upload.mjs'\nimport { _uploadData, findDirectories } from './image-browser-view-methods/sink.mjs'\n\n\nexport default class ImageBrowserView extends View {\n\t/**\n\t * Construct a new file browser\n\t * @param {object} options \n\t * @param {FileSink} options.sink The file to use as a file source\n\t * @param {boolean} [options.imagesOnly] Set to true if you would like to display only images\n\t * @param {boolean} [options.loadStyles] True by default. If true, default styles will be loaded.\n\t * @param {boolean} [options.allowFileSelection] Set to true so that selected files are marked\n\t * @param {EventNotificationPanel} [options.eventNotificationPanel] The panel which status messages will be added to.\n\t * @param {string} [options.startingDirectory] Opens to that directory path if it exists\n\t * @param {boolean} [options.deleteWithoutConfirm] False by default\n\t * @param {boolean} [options.ignoreGlobalEvents] False by default, if true it will not listen to events like paste or keypresses\n\t * which occur on the document\n\t * @param {Emitter} [options.emitter] Emitter for various file events\n\t * @param {int} [options.listTriggerSize] If the number of items are over this limit, they are shown as a plain list by default\n\t * @param {int} [options.listLockSize] If the number of items are over this limit, they can't use anyting other than the plain list\n\t */\n\tconstructor(options) {\n\t\tsuper(options)\n\t\tthis.setIfNotSet('overCount', 0)\n\t\tthis.setIfNotSet('emitter', new Emitter())\n\t\tthis.setIfNotSet('fileUploadSelector', 'input[name=\"fileUpload\"]')\n\t\tthis.setIfNotSet('listTriggerSize', 100)\n\t\tthis.setIfNotSet('listLockSize', 200)\n\t\tthis.setIfNotSet('loadStyles', true)\n\t\t\n\t\tif(this.loadStyles) {\n\t\t\tloadStyles()\n\t\t}\n\t}\n\n\tpreinitialize() {\n\t\tthis.className = 'image-browser'\n\t\tthis.idInd = 1\n\t\tthis.nodes = {}\n\t\tthis.events = {\n\t\t\t'click .create-directory': 'createDirectory'\n\t\t\t, 'click .upload-file': '_uploadFileButton'\n\t\t\t, 'change [name=\"fileUpload\"]': '_uploadFile'\n\t\t\t, 'click .delete-file': 'deleteFile'\n\t\t\t, 'click .delete-directory': 'deleteDirectory'\n\t\t\t, 'click .variant-choice-box .details': 'showVariantDetails'\n\t\t\t, 'dblclick .variant-choice-box': 'showVariantDetails'\n\t\t\t, 'click .variant-choice-box': 'selectVariant'\n\t\t\t, 'click .view-icons button': 'changeFilesView'\n\t\t\t, 'keyup [name=\"filter\"]': 'applyFilter'\n\t\t\t, 'change [name=\"filter\"]': 'applyFilter'\n\t\t\t, 'click .clear-filter': 'clearFilter'\n\t\t\t, 'dragenter .': 'dragEnter'\n\t\t\t, 'dragleave .': 'dragLeave'\n\t\t\t, 'dragover .': 'dragOver'\n\t\t\t, 'drop .': 'handleDrop'\n\t\t}\n\n\t\tthis.pasteListener = handlePaste.bind(this)\n\t\tdocument.addEventListener('paste', this.pasteListener)\n\t}\n\t\n\tcleanup() {\n\t\tdocument.removeEventListener('paste', this.pasteListener)\n\t}\n\n\tasync render() {\n\t\tthis.el.innerHTML = imageBrowserFrame(this.model)\n\t\tthis.data = []\n\n\t\tthis.rootDirectory = await this.sink.getFullFileInfo('')\n\t\tthis.rootDirectory.name = \"Files\"\n\t\tlet rootNode = this.rootNode = this._fileToKalpaNode(this.rootDirectory)\n\t\tthis.data.push(rootNode)\n\n\t\tlet directories = await this.findDirectories()\n\t\tthis._sortFiles(directories)\n\n\t\tthis.data.push(...directories.map(this._fileToKalpaNode.bind(this)))\n\t\tlet treeView = new KalpaTreeView({\n\t\t\tdata: this.data\n\t\t})\n\t\tlet treeBox = this.el.querySelector('.treebox')\n\t\ttreeView.appendTo(treeBox)\n\t\tawait treeView.render()\n\t\tlet tree = this.tree = treeView.tree\n\t\ttree.on('select', (node) => {\n\t\t\tthis.setCurrentNode(node)\n\t\t})\n\t\ttree.on('selected', (node) => {\n\t\t\t// There's a bug, either in the browser or kalpa tree that causes it\n\t\t\t// not to examine if a scroll bar is needed for the tree if the content\n\t\t\t// area changes in a big way. Part of this bug may be that it's being\n\t\t\t// used in a grid which has some weird width/height effects\n\t\t\t// Anyway, we need to make sure the browser knows to examine the tree so\n\t\t\t// we change the height then change it back.\n\t\t\t// This event is triggered when kalpa-tree thinks it's done with transitions\n\n\t\t\tlet tree = this.el.querySelector('.tree')\n\t\t\ttree.style.height = '99.99999%'\n\t\t\tsetTimeout(() => {\n\t\t\t\ttree.style.height = '100%'\n\t\t\t}, 100)\n\t\t})\n\t\tif (this.startingDirectory) {\n\t\t\tfor (let node of Object.values(this.tree.nodes)) {\n\t\t\t\tif (node.file && node.file.relPath && node.file.relPath == this.startingDirectory) {\n\t\t\t\t\ttree.select(node.id)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\ttree.select(1)\n\t\t}\n\t}\n\n\tasync setCurrentNode(node) {\n\t\tthis.currentNode = node\n\t\tthis.cleanFileInfo()\n\t\tlet choicesBoxes = this.el.querySelector('.choice-boxes')\n\t\tlet info = await this.sink.getFullFileInfo(node.file.relPath)\n\t\tlet variantValues = this.createVariantValues(info)\n\n\n\t\tif(variantValues.length > this.listTriggerSize) {\n\t\t\tthis.changeFilesViewToClass('list-text')\n\t\t}\t\n\n\t\tlet content = ''\n\t\tfor (let child of variantValues) {\n\t\t\tcontent += variantChoiceBox(child)\n\t\t}\n\n\n\t\tchoicesBoxes.innerHTML = ''\n\t\tchoicesBoxes.insertAdjacentHTML('beforeend', content)\n\n\t\tfor (let i = 0; i < choicesBoxes.children.length; i++) {\n\t\t\tchoicesBoxes.children[i].variant = variantValues[i]\n\t\t}\n\t\tthis.el.querySelector('.box-holder').scrollTop = 0\n\t\tthis.applyFilter()\n\t}\n\n\t// uploads\n\t_uploadGuidedImageFile = _uploadGuidedImageFile\n\t_uploadGuidedFile = _uploadGuidedFile\n\t_uploadAutomaticImageFile = _uploadAutomaticImageFile\n\tuploadFiles = uploadFiles\n\t_uploadFileButton = _uploadFileButton\n\t_uploadFile = _uploadFile\n\n\t// file-obj-manipulation\n\tcreateVariantValues = createVariantValues\n\t_getFilesFromEvent = _getFilesFromEvent\n\t_getAssociatedRealFiles = _getAssociatedRealFiles\n\t_createAccessUrl = _createAccessUrl\n\tescapeAccessUrl = escapeAccessUrl\n\tgetSelectedFiles = getSelectedFiles\n\t_transformRelativeUrlToPublic = _transformRelativeUrlToPublic\n\tgetSelectedUrl = getSelectedUrl\n\tgetSelectedUrlExtFromMeta = getSelectedUrlExtFromMeta\n\n\t// create-directory \n\tcreateDirectory = createDirectory\n\n\t// drag-and-drop\n\tgetDropCoverSelector = getDropCoverSelector\n\thandleDrop = handleDrop\n\tisFileTypeDrag = isFileTypeDrag\n\tdragEnter = dragEnter\n\tdragLeave = dragLeave\n\tdragOver = dragOver\n\thandlePaste = handlePaste\n\t_cleanupDropDone = _cleanupDropDone\n\n\t// view-interactions\n\tchangeFilesView = changeFilesView\n\tchangeFilesViewToClass = changeFilesViewToClass\n\tapplyFilter = applyFilter\n\tclearFilter = clearFilter\n\tselectVariant = selectVariant\n\tshowVariantDetails = showVariantDetails\n\tsetFolderInfo = setFolderInfo\n\tcleanFileInfo = cleanFileInfo\n\n\t// utils\n\tsanitizeFileName = sanitizeFileName\n\t_sortFiles = _sortFiles\n\t_compareVariants = _compareVariants\n\t_determineExtensions = _determineExtensions\n\t_determineSizes = _determineSizes\n\t_join = _join\n\t_determineParentPath = _determineParentPath\n\t_fileToKalpaNode = _fileToKalpaNode\n\t_formatBytes = formatBytes\n\t_isImageFile = _isImageFile\n\tsetIfNotSet = setIfNotSet\n\t_addPending = _addPending\n\n\t// delete\n\tdeleteFile = deleteFile\n\tdeleteDirectory = deleteDirectory\n\n\t// sink\n\t_uploadData = _uploadData\n\tfindDirectories = findDirectories\n\n}\n","import { Dialog } from '@webhandle/dialog'\nimport ImageBrowserView from './image-browser-view.mjs'\n\n/**\n * Selects a file.\n * @param {Object} [options]\n * @param {string} [options.title] The dialog box title\n * @param {boolean} [options.chooseOnUpload] If true, uploading a file causes the dialog to close and the URL of uploaded\n * file to be returned\n */\nexport class FileSelectDialog extends Dialog {\n\tconstructor(options) {\n\t\tsuper(Object.assign({\n\t\t\ttitle: 'Select A File'\n\t\t\t, body: `<div class=\"webhandle-file-tree-image-browser\" style=\"width: 87vw;\"> </div>`\n\t\t\t, afterOpen: function () {\n\n\t\t\t\tlet treeHolder = this.el.querySelector('.body').querySelector('.webhandle-file-tree-image-browser')\n\t\t\t\tif (treeHolder) {\n\t\t\t\t\tlet options = {\n\t\t\t\t\t\tsink: this.sink\n\t\t\t\t\t\t, imagesOnly: this.imagesOnly\n\t\t\t\t\t\t, eventNotificationPanel: this.eventNotificationPanel\n\t\t\t\t\t\t, startingDirectory: this.startingDirectory\n\t\t\t\t\t\t, deleteWithoutConfirm: this.deleteWithoutConfirm\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tlet imageBrowserView = this.imageBrowserView = new ImageBrowserView(options)\n\t\t\t\t\tif(this._createAccessUrl) {\n\t\t\t\t\t\timageBrowserView._createAccessUrl = this._createAccessUrl\n\t\t\t\t\t}\n\t\t\t\t\tif(this._transformRelativeUrlToPublic) {\n\t\t\t\t\t\timageBrowserView._transformRelativeUrlToPublic = this._transformRelativeUrlToPublic\n\t\t\t\t\t}\n\t\t\t\t\timageBrowserView.appendTo(treeHolder)\n\t\t\t\t\timageBrowserView.render()\n\n\t\t\t\t\timageBrowserView.emitter.on('select', async (evt) => {\n\n\t\t\t\t\t})\n\t\t\t\t\timageBrowserView.emitter.on('upload', async (evt) => {\n\t\t\t\t\t\tif(this.chooseOnUpload) {\n\t\t\t\t\t\t\tthis.imageBrowserView.cleanup()\n\t\t\t\t\t\t\tthis.cleanup()\n\t\t\t\t\t\t\tthis.resolve({\n\t\t\t\t\t\t\t\turl: evt.accessUrls[0]\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\t, chooseOnUpload: true\n\t\t}, options\n\t\t))\n\t}\n\tasync okay() {\n\t\tlet result = {\n\t\t\tselection: this.imageBrowserView.getSelectedFiles()\n\t\t}\n\t\tresult.url = await this.imageBrowserView.getSelectedUrl(result.selection)\n\t\tthis.imageBrowserView.cleanup()\n\t\tthis.cleanup()\n\t\tthis.resolve(result)\n\t}\n\tcancel() {\n\t\tthis.resolve(false)\n\t\tthis.imageBrowserView.cleanup()\n\t\tthis.cleanup()\n\t}\n\tclose() {\n\t\tthis.resolve(false)\n\t\tthis.imageBrowserView.cleanup()\n\t\tthis.cleanup()\n\t}\n\n}"],"names":["module","exports","s","preserveCR","replace","imageExtensions","smallerSizeExt","imageSizeExt","findPreviewVariant","isFileImage","makeVariantImage","fileBasename","findPrimaryVariant","setSpecialVariants","variantDefinition","preview","variants","primary","directoryContents","files","filter","child","directory","definitions","name","toLowerCase","endsWith","imageFiles","getVariant","baseName","variant","definition","definitionFile","imageVariant","map","push","Array","from","Object","keys","length","values","forEach","substring","lastIndexOf","size","img","ext","fallbackSizeExt","fallbackImgageExtensions","item","nameLower","isFileImageName","file","info","noExt","sizeString","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","add","addTemplate","content","d","key","o","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","imageBrowserFrame","variantChoiceBox","guidedImageUploadForm","guidedFileUploadForm","formatBytes","bytes","decimals","dm","i","Math","floor","log","parseFloat","pow","toFixed","loadStyles","document","createElement","classList","style","position","left","body","appendChild","color","window","getComputedStyle","remove","areStylesLoaded","link","href","rel","head","Streamish","constructor","this","handles","on","evt","handle","emit","args","apply","removeListener","eventName","listener","func","Emitter","base","EventTarget","target","super","innerEventTarget","addEventListener","nativeListener","event","detail","dispatchEvent","_makeEvent","removeEventListener","CustomEvent","Event","async","deleteFile","selected","sel","getSelectedFiles","names","deleteWithoutConfirm","prom","title","join","open","note","path","relPath","eventNotificationPanel","addNotification","model","status","headline","sink","rm","ttl","boxes","emitter","type","deleteDirectory","currentNode","recursive","curSelected","tree","parent","removeNode","select","id","_join","parts","part","_determineParentPath","split","pop","_fileToKalpaNode","node","idInd","label","loaded","nodes","parentId","_determineExtensions","extensions","Set","imgVariant","result","sort","a","b","localeCompare","_determineSizes","min","max","stat","_sortFiles","one","two","_compareVariants","sanitizeFileName","_isImageFile","startsWith","includes","setIfNotSet","value","_addPending","changeFilesView","className","getAttribute","changeFilesViewToClass","choiceBoxes","el","querySelector","querySelectorAll","button","applyFilter","setTimeout","allVariants","indexOf","setFolderInfo","clearFilter","selectVariant","currentSelected","ctrlKey","shiftKey","cur","contains","previousElementSibling","toggle","showVariantDetails","closest","_getAssociatedRealFiles","safeThumbnail","escapeAccessUrl","accessUrl","_formatBytes","showCancelButton","then","fileCount","variantCount","byteCount","nonImages","innerHTML","listTriggerSize","listLockSize","cleanFileInfo","getDropCoverSelector","handleDrop","uploadType","dropSquare","_cleanupDropDone","preventDefault","_getFilesFromEvent","uploadFiles","isFileTypeDrag","fileType","dataTransfer","items","kind","dragEnter","overCount","dragLeave","dragOver","cover","handlePaste","ignoreGlobalEvents","clipboardData","createDirectory","data","directoryPath","mkdir","getFullFileInfo","options","stream","expand","addSoftBreaks","txt","chars","chrs","c","breakOnChars","createVariantValues","children","variantValues","used","remainingChildren","thumbnailIcon","thumbnail","_createAccessUrl","imagesOnly","sizes","safeBaseName","foundItems","webkitGetAsEntry","entry","isDirectory","getAsFile","File","url","encodeURIComponent","urlEscapeChars","_transformRelativeUrlToPublic","getSelectedUrl","selectedFiles","chosen","defData","read","JSON","parse","getSelectedUrlExtFromMeta","e","displaySize","altText","baseImageName","char","match","dataToImage","Promise","resolve","reject","finalImage","objectUrl","Image","src","imageBlob","Blob","URL","createObjectURL","finish","revokeObjectURL","complete","resizeImage","imageData","maxWidth","quality","outputFormat","resizeImg","ratio","naturalWidth","maxHeight","naturalHeight","resizeCanvas","width","height","ctx","getContext","clearRect","drawImage","toBlob","blob","console","getImageStats","types","getExtension","mime","webpMime","makeImageSet","singleDensityWidth","doubleDensityInput","baseFileName","source","stats","Date","getTime","doubleDensityWidth","suffixes","stringify","nameParts","_uploadGuidedImageFile","getFileImageStats","nativeName","mainUrl","makeImageData","parseInt","meta","fileName","_uploadData","fallback","_uploadGuidedFile","_uploadAutomaticImageFile","uploadedAccessUrls","uploaded","setCurrentNode","accessUrls","_uploadFileButton","fileUploadSelector","click","_uploadFile","input","write","findDirectories","results","events","find","ImageBrowserView","preinitialize","pasteListener","bind","cleanup","render","rootDirectory","rootNode","directories","treeView","treeBox","appendTo","startingDirectory","choicesBoxes","insertAdjacentHTML","scrollTop","FileSelectDialog","assign","afterOpen","treeHolder","imageBrowserView","chooseOnUpload","okay","selection","cancel","close"],"sourceRoot":""}
@@ -1,13 +1,16 @@
1
-
1
+ import {tripartite} from "tripartite"
2
2
  import t3 from './webhandle-tree-image-browser/image-browser-frame.tri';
3
3
  import t4 from './webhandle-tree-image-browser/variant-choice-box.tri'
4
4
  import t5 from './webhandle-tree-image-browser/extension-pill.tri'
5
5
  import t6 from './webhandle-tree-image-browser/guilded-image-upload-form.tri'
6
6
  import t7 from './webhandle-tree-image-browser/guilded-file-upload-form.tri'
7
7
 
8
+ function add(item) {
9
+ return tripartite.addTemplate(item.name, item.content)
10
+ }
8
11
 
9
- export let imageBrowserFrame = t3
10
- export let variantChoiceBox = t4
11
- export let extensionPill = t5
12
- export let guidedImageUploadForm = t6
13
- export let guidedFileUploadForm = t7
12
+ export let imageBrowserFrame = add(t3)
13
+ export let variantChoiceBox = add(t4)
14
+ export let extensionPill = add(t5)
15
+ export let guidedImageUploadForm = add(t6)
16
+ export let guidedFileUploadForm = add(t7)
@@ -1,65 +0,0 @@
1
- import Dialog from 'ei-dialog'
2
- import formValueInjector from 'form-value-injector'
3
- import gatherFormData from '@webhandle/gather-form-data'
4
-
5
-
6
- export class FormAnswerDialog extends Dialog {
7
- /**
8
- *
9
- * @param {Object} options Properties to create the dialog box. In addition to the properties from Dialog
10
- * there those below.
11
- * @param {Object} options.data The data which will be used to populate the controls in the dialog
12
- */
13
- constructor(options) {
14
- super(Object.assign({}, options,
15
- {
16
- on: {
17
- '.btn-ok': () => {
18
- this.resolve(this.gatherData())
19
- return true
20
- },
21
- '.mask': () => {
22
- this.resolve()
23
- return true
24
- },
25
- '.btn-cancel': () => {
26
- this.resolve()
27
- return true
28
- }
29
- }
30
-
31
- }
32
- ))
33
- if (this.afterOpen) {
34
- this.afterOpenOriginal = this.afterOpen
35
- }
36
- this.afterOpen = function (bodyElement, self) {
37
- if (this.data) {
38
- bodyElement.innerHTML = formValueInjector(bodyElement.innerHTML, this.data)
39
- }
40
- let firstInput = bodyElement.querySelector('input, textarea')
41
- if (firstInput) {
42
- firstInput.focus()
43
- }
44
-
45
- if (this.afterOpenOriginal) {
46
- this.afterOpenOriginal(bodyElement, self)
47
- }
48
- }
49
- }
50
- gatherData() {
51
- let dialogBody = document.querySelector(this.getBodySelector())
52
- return gatherFormData(dialogBody)
53
- }
54
-
55
- async open() {
56
- this.promise = new Promise((resolve, reject) => {
57
- this.resolve = resolve
58
- this.reject = reject
59
- })
60
- super.open()
61
-
62
- return this.promise
63
- }
64
-
65
- }
@@ -1,36 +0,0 @@
1
- import Dialog from 'ei-dialog'
2
-
3
- export class InfoDialog extends Dialog {
4
- constructor(options) {
5
- super(Object.assign({}, options,
6
- {
7
- on: {
8
- '.btn-ok': () => {
9
- this.resolve()
10
- return true
11
- },
12
- '.mask': () => {
13
- this.resolve()
14
- return true
15
- },
16
- '.btn-cancel': () => {
17
- this.resolve()
18
- return true
19
- }
20
- }
21
-
22
- }
23
- ))
24
- }
25
-
26
- async open() {
27
- this.promise = new Promise((resolve, reject) => {
28
- this.resolve = resolve
29
- this.reject = reject
30
- })
31
- super.open()
32
-
33
- return this.promise
34
- }
35
-
36
- }