New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

material

Package Overview
Dependencies
Maintainers
0
Versions
74
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

material - npm Package Compare versions

Comparing version 0.9.21 to 0.9.22

src/class/app.js

1

index.js

@@ -10,2 +10,3 @@ // base classes

import Checkbox from './src/checkbox'
import ColorPicker from './src/colorpicker'
import DateHour from './src/datehour'

@@ -12,0 +13,0 @@ import Dialog from './src/dialog'

2

package.json
{
"name": "material",
"version": "0.9.21",
"version": "0.9.22",
"description": "A lightweight implementation of Material Design Components for the web - ES6",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -5,3 +5,6 @@ import build from '../module/build'

class Component {
static base = 'component'
static defaults = {
class: 'component',
mixins: []
}

@@ -11,24 +14,24 @@ constructor (options) {

// Apply any mixins first
const mixins = this.options.mixins || []
mixins.forEach(mixin => Object.assign(this, mixin))
for (let i = 0; i < mixins.length; i++) {
Object.assign(this, mixins[i])
}
// Build the component
build(this)
}
destroy () {
// console.log('destroy')
async destroy () {
console.log('destroy')
if (this.options.transition && this.element) {
this.element.classList.remove('show')
if (this.underlay) {
this.underlay.classList.remove('show')
}
setTimeout(() => {
dom.destroy(this.element)
if (this.underlay) dom.destroy(this.underlay)
}, this.options.transition)
await new Promise(resolve =>
setTimeout(() => {
dom.destroy(this.element)
if (this.underlay) dom.destroy(this.underlay)
resolve()
}, this.options.transition)
)
} else {

@@ -35,0 +38,0 @@ dom.destroy(this.element)

import Component from './component'
import events from '../module/events'
import emitter from '../module/emitter'
class Control extends Component {
static base = 'control'
static defaults = {
base: 'control',
...Component.defaults,
events: []
}
constructor (options) {
super(options)
// Initialize event storage
this.events = {}
// Mix in emitter functionality
Object.assign(this, emitter)
// Attach DOM events if specified in options
if (this.options.events) {

@@ -16,22 +27,19 @@ events.attach(this.options.events, this)

on (event, listener) {
this.events[event] ??= []
this.events[event].push(listener)
destroy () {
// First cleanup event listeners
if (this.options.events) {
events.detach(this.options.events, this)
}
return this
}
// Clean up emitter subscriptions
this.removeAll()
emit (event, ...args) {
this.events?.[event]?.forEach(listener => listener.apply(this, args))
// Emit destroy event before DOM removal
this.emit('destroy')
return this
}
// Clear event storage
this.events = null
destroy () {
// if (this.options.events) {
// events.detach(this.options.events, this)
// }
// Let parent handle DOM cleanup
super.destroy()
this.emit?.('destroy')
}

@@ -38,0 +46,0 @@ }

import Component from './component'
import events from '../module/events'
import build from '../form/build'
import emitter from '../module/emitter'
class Form {
static base = 'form'
static defaults = {
base: 'form',
events: []
}

@@ -12,9 +16,6 @@ constructor (options) {

const mixins = this.options.mixins || []
mixins.forEach(mixin => Object.assign(this, mixin))
for (let i = 0; i < mixins.length; i++) {
Object.assign(this, mixins[i])
}
Object.assign(this, build, emitter)
Object.assign(this, build)
this.build(this)

@@ -28,20 +29,4 @@

}
on (event, listener) {
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].push(listener)
return this
}
emit (event, ...args) {
if (this.events[event]) {
this.events[event].forEach(listener => listener.apply(this, args))
}
return this
}
}
export default Form

@@ -1,30 +0,29 @@

import Component from './component'
import events from '../module/events'
import Control from './control'
import display from '../mixin/display'
class View extends Component {
static base = 'view'
class View extends Control {
static defaults = {
base: 'view',
...Control.defaults,
display: {}
}
constructor (options) {
// Let Control handle all the event setup
super(options)
this.events = {}
if (this.options.events) {
events.attach(this.options.events, this)
}
// Add any View-specific initialization here
// For example, if View needs display functionality:
Object.assign(this, display)
}
on (event, listener) {
this.events[event] ??= []
this.events[event].push(listener)
// If View needs any special cleanup:
destroy () {
// Do View-specific cleanup first
return this
// Then let Control handle event cleanup
super.destroy()
}
emit (event, ...args) {
this.events?.[event]?.forEach(listener => listener.apply(this, args))
return this
}
}
export default View
export default {
cancel (ev) {
// console.log('cancel', this.info, this.mode)
ev.preventDefault()
if (ev) ev.preventDefault()

@@ -6,0 +5,0 @@ this.render(this.info)

@@ -9,13 +9,4 @@

for (const field in this.field) {
if (this.field.hasOwnProperty(field)) {
this.bindControl(this.field[field])
}
}
for (const file in this.file) {
if (this.file.hasOwnProperty(file)) {
this.bindControl(this.file[file])
}
}
Object.keys(this.field).forEach(field => this.bindControl(this.field[field]))
Object.keys(this.file).forEach(file => this.bindControl(this.file[file]))
},

@@ -43,3 +34,3 @@

changeMode (mode) {
// console.log('changeMode', mode)
// console.log('changeMode', mode, this.options.class)

@@ -56,9 +47,9 @@ if (mode === 'update' && this.enableControls) {

bindControl (control) {
// console.log('bindControl')
// console.log('bindControl', control.class)
if (control && control.on) {
control.on('change', () => {
// console.log('change', control, this.mode)
if (this.mode === 'read') {
this.setMode('update')
}
if (this.isModified) this.isModified()
this.setMode('update')
this.emit('changed', this.options.class)
console.log('isModified', this.isModified)
})

@@ -69,3 +60,2 @@ }

enableControls () {
// console.log('enableControls')
const controls = this.options.controls || ['submit', 'cancel']

@@ -80,2 +70,4 @@

}
this.emit('enableControls')
},

@@ -82,0 +74,0 @@

import { byString } from '../module/object'
export default {
/**
* Initializes form data with fields and files
* @returns {FormData} Initialized form data
*/
initData () {
// console.log('submit', this.mode)
try {
const data = new FormData()
const data = new FormData()
if (this.mode !== 'create') {
this.appendSysinfo(data)
}
if (this.mode !== 'create') {
this.appendSysinfo(data)
return this.appendFiles(this.appendFields(data))
} catch (error) {
console.error('Error initializing form data:', error)
throw new Error('Failed to initialize form data')
}
},
this.appendFields(data)
this.appendFiles(data)
return data
/**
* Fetches and sets data for the form
* @param {Object} user - User data object
* @returns {Promise<void>}
*/
async getData () {
// console.log('getData')
Object.entries(this.field).forEach(([fieldName, field]) => {
console.log('fieldName', fieldName)
})
},
/**
* Appends system information to form data
* @param {FormData} data - FormData instance
* @returns {FormData} Updated FormData
*/
appendSysinfo (data) {
const sys = this.options.sysinfo
for (let i = 0; i < sys.length; i++) {
// console.log('sys', sys[i], this.info[sys[i]])
let name = sys[i]
if (sys[i] === '_id') name = 'id'
data.append(name, this.info[sys[i]])
// console.log('appendSysinfo')
if (!Array.isArray(this.options?.sysinfo)) {
return data
}
this.options.sysinfo.forEach(field => {
const name = field === '_id' ? 'id' : field
const value = this.info?.[field]
if (value !== undefined) {
data.append(name, value)
}
})
return data
},
/**
* Appends form fields to FormData
* @param {FormData} data - FormData instance
* @returns {FormData} Updated FormData
*/
appendFields (data) {
for (const field in this.field) {
// console.log('field', field)
if (this.field.hasOwnProperty(field)) {
// console.log('check field', field)
const value = this.field[field].get()
if (value !== null) {
if (this.mode === 'update' && this.options.update && this.options.update.modifiedOnly) {
const modified = this.isModified(field, value)
if (modified) {
data.append(field, value)
}
} else {
data.append(field, value)
}
}
}
if (!this.field || !(data instanceof FormData)) {
return data
}
Object.entries(this.field).forEach(([fieldName, field]) => {
const value = field?.get?.()
if (value === null || value === undefined) {
return
}
const shouldAppend = this.mode === 'update' &&
this.options?.update?.modifiedOnly
? this.isModified(fieldName, value)
: true
if (shouldAppend) {
data.append(fieldName, value)
}
})
return data
},
/**
* Appends file inputs to FormData
* @param {FormData} data - FormData instance
* @returns {FormData} Updated FormData
*/
appendFiles (data) {
// console.log('appendFiles', this.file)
for (const file in this.file) {
// console.log('this file', this.file, this.file[file].input)
// console.log('file', file, this.file[file])
if (this.file.hasOwnProperty(file) && this.file[file].input && this.file[file].input.value) {
data.append(file, this.file[file].input.files[0])
}
if (!this.file || !(data instanceof FormData)) {
return data
}
Object.entries(this.file)
.filter(([, fileField]) => {
const input = fileField?.input
return input?.value && input?.files?.length > 0
})
.forEach(([fileName, fileField]) => {
data.append(fileName, fileField.input.files[0])
})
return data
},
isModified (field, value) {
const initial = byString(this.info, field)
/**
* Gets structured field data
* @returns {Object} Field data object
*/
getFieldData () {
if (!this.field) {
return {}
}
if (typeof initial === 'number') {
value = Number(value)
return Object.entries(this.field).reduce((acc, [fieldName, field]) => {
const value = field?.get?.()
if (value !== null && value !== undefined) {
acc[fieldName] = value
}
return acc
}, {})
},
/**
* Gets structured file data
* @returns {Object} File data object
*/
getFileData () {
if (!this.file) {
return {}
}
if (initial !== value) {
// console.log('field', field, typeof value, value)
return true
} else {
return Object.entries(this.file).reduce((acc, [fileName, fileField]) => {
const input = fileField?.input
if (input?.value && input?.files?.length > 0) {
acc[fileName] = input.files[0]
}
return acc
}, {})
},
/**
* Checks if any fields have been modified from their initial values
* @returns {boolean} True if any field is modified
*/
isModified () {
// console.log('checkModified', this.options.class)
// console.log('field', this.field)
// console.log('info', this.info)
if (!this.field || !this.info) {
return false
}
let modified = false
Object.entries(this.field).forEach(([fieldName]) => {
if (this.isFieldModified(fieldName)) {
modified = true
}
})
this.modified = modified
// console.log('modified', modified)
return modified
},
/**
* Checks if a field value has been modified
* @param {string} fieldName - Field name
* @returns {boolean} True if modified
*/
/**
* Checks if a specific field value has been modified from its initial value
* @param {string} fieldName - Field name to check
* @returns {boolean} True if the field is modified
*/
isFieldModified (fieldName) {
// console.log('isFieldModified', fieldName)
const currentValue = this.field[fieldName]?.get?.() ?? undefined
const initialValue = this.info[fieldName] ?? undefined
// Special case for text fields: treat undefined and empty string as equivalent
if (typeof currentValue === 'string' || currentValue === undefined) {
const normalizedCurrent = currentValue || ''
const normalizedInitial = initialValue || ''
return normalizedCurrent !== normalizedInitial
}
// Handle number comparisons
if (typeof initialValue === 'number') {
const parsedCurrent = Number(currentValue)
return isNaN(parsedCurrent) ? true : parsedCurrent !== initialValue
}
// Standard null/undefined checks
if (initialValue === undefined || initialValue === null) {
return currentValue !== null && currentValue !== undefined
}
log.error('modified', initialValue !== currentValue)
return initialValue !== currentValue
}
}

@@ -0,30 +1,23 @@

import request from '../module/request'
export default {
fetch (option) {
async fetch (option) {
// console.log('fetch', this.options.route, option.method)
fetch(this.options.route, {
method: option.method,
body: option.formData
}).then(r => r.json()).then(info => {
if (info.error) {
// console.log('Error: ' + info.error)
if (this.error) {
this.error(info)
}
} else {
// console.log('updated', info, this.mode)
if (this.mode === 'create') {
this.emit('created', info)
this.mode = 'read'
} else {
this.info = info
this.emit('updated', info)
this.mode = 'read'
}
if (this.success) {
this.success(info)
}
}
})
const info = await request(this.options.route, option.method, option.formData)
// console.log('updated', info, this.mode)
if (this.mode === 'create') {
this.emit('created', info)
this.mode = 'read'
} else {
this.info = info
this.emit('updated', info)
this.mode = 'read'
}
if (this.success) {
this.success(info)
}
}
}

@@ -15,6 +15,6 @@ import dot from '../module/dot'

if (!info) return
// console.log('dotified', this.field, info)
if (!info) return
for (const field in this.field) {

@@ -21,0 +21,0 @@ if (this.field.hasOwnProperty(field)) {

export default {
submit (ev) {
ev.preventDefault()
async submit (ev) {
if (ev) ev.preventDefault()
// console.log('submit', this.mode)

@@ -9,6 +9,11 @@

// for (const pair of data.entries()) {
// console.log(`${pair[0]}: ${pair[1]}`)
// }
// console.log('data', data)
if (this.update) {
this.update(data)
// console.log('this.update', this.update)
await this.update(data)
} else {

@@ -22,2 +27,3 @@ this.setMethod(data)

setMethod (formData) {
// console.log('setMethod', this.mode)
let method = 'PUT'

@@ -24,0 +30,0 @@ if (this.mode === 'create') {

@@ -0,4 +1,6 @@

import request from '../module/request'
export default {
update (data, options) {
// console.log('update', data, options)
async update (body, options) {
// console.log('update', body, options)
// console.log('mode', this.mode)

@@ -9,39 +11,34 @@ options = options || {}

const method = options.method ||
this.options[this.mode].method ||
'put'
this.options[this.mode].method ||
'PUT'
const action = options.action ||
this.options[this.mode].action ||
this.options.action
this.options[this.mode].action ||
this.options.action
if (this.beforeCreate) {
this.beforeCreate(data)
this.beforeCreate(body)
}
fetch(action, {
method,
body: data
}).then((resp) => {
// console.log('resp', resp)
return resp.json()
}).then(info => {
// console.log('update', info)
if (info.error) {
// console.log('Error: ' + info.error)
if (this.error) {
this.error(info)
}
// console.log('request', action, method, body)
const info = await request(action, method, body)
// console.log('update', info)
if (info.error) {
// console.log('Error: ' + info.error)
if (this.error) {
this.error(info)
}
} else {
// console.log('info', this.mode, info)
if (this.mode === 'create') {
this.emit('created', info)
this.setMode('read')
} else {
// console.log('info', this.mode, info)
if (this.mode === 'create') {
this.emit('created', info)
this.setMode('read')
} else {
this.emit('updated', info)
this.setMode('read')
}
this.info = info
this.emit('updated', info)
this.setMode('read')
}
})
this.info = info
}
}
}

@@ -103,3 +103,8 @@ import scrollbar from '../module/scrollbar'

if (this.statusDisplay) {
const percent = parseInt(progress / this.count * 100)
let percent = parseInt(progress / this.count * 100)
if (progress > this.count) {
percent = 100
progress = this.count
}
this.statusDisplay('count', percent + '% | ' + progress + ' / ' + this.count)

@@ -106,0 +111,0 @@ }

@@ -12,3 +12,8 @@ export default {

// console.log('statusCount', count)
//
let items = 'items'
if (count < 1) {
items = 'item'
}
if (this.status && this.status.count && this.status.count.name) {

@@ -15,0 +20,0 @@ items = this.status.count.name

@@ -8,2 +8,4 @@ import { create } from '../module/layout'

if (!info) return
this.getUpdatedInfo(info[this.dataId])

@@ -10,0 +12,0 @@ },

@@ -138,3 +138,3 @@ import passiveEvents from '../module/passive'

const progress = Math.ceil((scrollTop / self.itemHeight) + self.itemsByScreen) - 1
// console.log('progress', progress)
// console.log('progress', progress, scrollTop, self.itemHeight)
self.emit('progress', progress)

@@ -141,0 +141,0 @@

@@ -0,22 +1,54 @@

// Event emitter mixin that can be extended into other objects
export default {
on (event, cb) {
this.event = this.event || {}
this.event[event] = this.event[event] || []
this.event[event].push(cb)
// Initialize the events storage if needed
_initEvents () {
this.events = this.events || {}
},
// Add an event listener
on (event, listener) {
this._initEvents()
// Use nullish coalescing assignment for array initialization
this.events[event] ??= []
this.events[event].push(listener)
return this
},
off (event, cb) {
this.event = this.event || {}
if (event in this.event === false) return
this.event[event].splice(this.event[event].indexOf(cb), 1)
// Emit an event with optional arguments
emit (event, ...args) {
this._initEvents()
// Use optional chaining to safely access and iterate events
this.events[event]?.forEach(listener => {
try {
listener.apply(this, args)
} catch (error) {
console.error(`Error in event listener for ${event}:`, error)
}
})
return this
},
emit (event /* , args... */) {
this.event = this.event || {}
if (event in this.event === false) return
for (let i = 0; i < this.event[event].length; i++) {
this.event[event][i].apply(this, Array.prototype.slice.call(arguments, 1))
// Remove a specific listener for an event
off (event, listener) {
this._initEvents()
const listeners = this.events[event]
if (listeners?.length) {
const index = listeners.indexOf(listener)
if (index !== -1) {
listeners.splice(index, 1)
}
}
return this
},
// Remove all listeners for an event or all events
removeAll (event) {
this._initEvents()
if (event) {
delete this.events[event]
} else {
this.events = {}
}
return this
}
}

@@ -7,3 +7,3 @@

*/
function e (instance, ev) {
const e = (instance, ev) => {
if (!ev) return instance

@@ -47,3 +47,3 @@ else if (!ev.match(/\./)) {

*/
function f (instance, func) {
const f = (instance, func) => {
if (!func) return

@@ -50,0 +50,0 @@

@@ -8,23 +8,52 @@ const request = async (

debug = false,
cache = 'no-store' // Adding cache parameter with a default value
cache = 'no-store'
) => {
// console.trace('request')
const defaultHeaders = {
Accept: 'application/json',
'Content-Type': 'application/json'
}
const options = {
method,
headers: { ...defaultHeaders, ...headers },
headers: {}, // We'll set headers based on body type
signal,
cache // Including the cache option in the request
cache
}
if (debug) {
console.log('debug', options)
// Handle headers and body based on body type
if (body) {
if (body instanceof FormData) {
// For FormData, don't set Content-Type - browser will set it automatically
options.body = body
options.headers = {
Accept: 'application/json',
...headers
}
if (debug) {
console.group('FormData Contents:')
for (const pair of body.entries()) {
console.log(`${pair[0]}: ${pair[1]}`)
}
console.groupEnd()
}
} else {
// For JSON data
options.headers = {
Accept: 'application/json',
'Content-Type': 'application/json',
...headers
}
options.body = JSON.stringify(body)
}
} else {
// No body, use default headers
options.headers = {
Accept: 'application/json',
'Content-Type': 'application/json',
...headers
}
}
if (body) {
options.body = JSON.stringify(body)
if (debug) {
console.group('Request Debug:')
console.log('URL:', url)
console.log('Method:', method)
console.log('Options:', { ...options, body: options.body instanceof FormData ? '[FormData]' : options.body })
console.groupEnd()
}

@@ -34,7 +63,11 @@

const response = await fetch(url, options)
if (!response.ok) {
// console.log('Error', response)
if (debug) {
console.error('Response error:', response.status, response.statusText)
}
throw new Error(`HTTP error! status: ${response.status}`)
}
// Determine response type based on 'Accept' header
// Handle response based on Accept header
if (headers.Accept === 'text/xml') {

@@ -49,3 +82,3 @@ return await response.text()

} else {
throw { error }
throw { error: error.message || 'Request failed' }
}

@@ -52,0 +85,0 @@ }

@@ -29,3 +29,3 @@ import emitter from './module/emitter'

this.options = Object.assign({}, Selector.defaults, options || {})
Object.assign(this, emitter, attach)
Object.assign(this, emitter, events)
}

@@ -32,0 +32,0 @@

@@ -113,3 +113,3 @@ // base

default:
this.setValue(prop, silent)
this.setValue(prop, value)
}

@@ -116,0 +116,0 @@

@@ -154,3 +154,3 @@ import EventEmitter from './mixin/emitter'

set (prop, value) {
set (prop, value, silent) {
switch (prop) {

@@ -167,3 +167,3 @@ case 'value':

default:
this.setValue(prop)
this.setValue(prop, value)
}

@@ -199,2 +199,11 @@

get () {
console.log('get', this.options.mode, this.selected[0])
if (this.options.mode === 'unique') {
return this.selected[0]
} else {
return this.selected
}
}
getValue () {
// console.log('get', this.selected)

@@ -201,0 +210,0 @@ if (this.options.mode === 'unique') {

@@ -170,4 +170,8 @@ import emitter from './module/emitter'

}
getValue () {
return this.input.value
}
}
export default Textfield
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc