Skip to content

[pull] main from enyo:main - #11

Merged
pull[bot] merged 15 commits into
AKJUS:mainfrom
enyo:main
Sep 13, 2026
Merged

pull[bot] merged 15 commits into
AKJUS:mainfrom
enyo:main

Conversation

@pull

@pull pull Bot commented Sep 13, 2026 •

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

enyo and others added 15 commits September 13, 2026 10:51
The four source files are now TypeScript, and the build emits declarations
into dist alongside the bundles. package.json gains a types field pointing at
them, so the package is typed from its own source rather than from
@types/dropzone, which is stuck at 5.7.9 and describes the v5 API.

The types were compared against @types/dropzone to make sure this is not a
step down. It covers all 52 options that package types, plus 44 it does not,
and three things came out of the comparison:

Options whose default is null are annotated -- `maxFiles: null as number |
null` -- rather than left as bare null, which carries no type at all. Eight
options were effectively `any` without this. Doing that surfaced seven places
reading an option that can be absent without checking, including resize(),
whose own documentation says width and height may be null while its signature
did not.

file.upload is a DropzoneFileUpload rather than Record<string, any>, so
progress, total, bytesSent, uuid and the chunking fields are typed and a
misspelled one is an error.

`on` and `emit` type their listener arguments per event, which is where
@types was genuinely ahead. It hand-writes 24 overloads; here the map is
derived from the option handler of the same name, so it covers all 29 events
and cannot drift. Unknown event names still work.

Two differences are deliberate rather than regressions. @types augments the
global HTMLElement with a required `dropzone` property, which is untrue of
every element that is not one. And it declares a jQuery plugin behind a ///
reference to @types/jquery, which pulls jQuery's types into every consumer.

The options type is derived, not written: DropzoneOptions is
Partial<typeof defaultOptions>, so all 96 options follow the source by
construction. Neither it nor the resolved form has an index signature, and
@types/dropzone does not have one either. One would accept any key at all, so
`maxFileSize` -- the wrong capitalisation of `maxFilesize` -- would pass
silently, and internally it was already hiding a read of
this.options.fixOrientation, an option that does not exist and never did.
That read was always undefined and its value is only ever tested for
truthiness, so it is false now. Custom keys still survive the merge at
runtime; reading one back off this.options needs a cast.

The statics live in the class rather than being declared there and assigned
1,700 lines further down. That split let the two halves disagree: discover()
was declared as returning void while it returns an array of dropzones, and
nothing could catch it. Dropzone.version now comes from package.json.
Dropzone.autoDiscover is not declared: it is documented, but nothing in 6.x
reads it.

initClass() is gone with it. It existed to write four properties onto the
prototype, which is why they needed `declare` rather than an initialiser --
and one of them was a bug: _thumbnailQueue was a single array shared by every
dropzone on the page, so two of them queued into the same list and rendered
from it under one lock. They are ordinary instance fields now, with a test
that fails against the old arrangement. Emitter moves to a static, since
being on the prototype was only ever a way to reach it.

The instance fields `version` and `defaultOptions` are removed. Neither was
ever assigned or read; defaultOptions in particular claimed a reachable
default that the roadmap lists as not existing.

strict is on, along with noUnusedLocals, noImplicitReturns,
noFallthroughCasesInSwitch, noImplicitOverride, and no unreachable code or
unused labels. noUnusedParameters is deliberately not among them: the option
handlers are public signatures whose parameter names document what arrives.

CI runs tsc --noEmit as its own step ahead of the build. The website is
checked too, which it never was: svelte-check covers the TypeScript inside
.svelte files, and --threshold warning means a warning fails the job.

Two more things the conversion found, both behaviour-preserving to fix: three
conditions in the EXIF code used a bitwise & between two comparisons, which
only works by coercing booleans to 0 and 1; and Dropzone.isValidFile assumed
acceptedFiles was a string and called .split on it, though an array was
already reaching it.
The website imports dropzone from the workspace, so svelte-check needs
dist/dropzone.d.ts to exist. Running the check first meant it ran against a
library with no declarations at all, and reported that as two errors in the
website: a named import of Dropzone that "can only be imported by using a
default import", and an implicit any for a rest parameter that is only
implicit because the method it is passed to had no type either.

Neither was about the website. Both came from the step order, which is why
this only appeared once someone imported Dropzone by name.

build-site.sh already builds the library as its first step, so moving the
check after it costs nothing.
The website imports dropzone from the workspace, which meant nothing here
could be type-checked until the library had been built: without
dist/dropzone.d.ts, svelte-check reported the missing declarations as errors
in the website. That is what turned a named import of Dropzone into "can only
be imported by using a default import" and an ordinary rest parameter into an
implicit any -- neither of which was about the website at all.

main, module and types now point at src/dropzone.ts, and publishConfig points
them back at dist for npm. pnpm swaps the fields when the package is packed
and drops publishConfig itself, so what is published is unchanged: main
dist/dropzone.js, module dist/dropzone.mjs, types dist/dropzone.d.ts.
Verified by packing the tarball and reading its package.json.

Two things had to be true for the source to compile under another package's
tsconfig, since that is now what happens:

The ambient declarations are referenced from dropzone.ts itself rather than
only being listed in this package's tsconfig, so EXIF and jQuery are found by
whoever is compiling it.

`element` is declared rather than definitely assigned. The constructor
assigns it, and under useDefineForClassFields -- which the website's config
has and this one does not -- a field declaration would overwrite what Emitter
provides.

The blast radius of compiling the source is the workspace only: everyone
installing from npm still gets the declarations, built here.

The end-to-end tests and the standalone bundle still need the build, and so
does dropzone/dist/dropzone.css, which the website imports. Once the
stylesheet is plain CSS that import can point at src as well.
Neither README nor the documentation mentioned TypeScript at all, and the
thing a TypeScript user most needs to be told is to uninstall
@types/dropzone: it stopped at 5.7.9 and describes the v5 API, so it
disagrees with what they are using.

Both READMEs say so, and the installation page gains a TypeScript section
with the two things worth knowing beyond `it just works` -- that listener
arguments are inferred from the event name, and that overriding a handler
gives a typed `this`. Both examples were compiled against the built
declarations rather than written from memory.

The links to the options source were stale twice over: they pointed at
src/options.js, which moved into packages/dropzone in the monorepo change and
is now .ts. All five are corrected. The line anchor in events.md is dropped
rather than renumbered -- it was pointing 50 lines off already, and would go
stale again with the next edit.
Trimming the section left DropzoneFile imported but no longer used: the
listener's argument is inferred, which is what the example is there to show.
Anyone copying it with noUnusedLocals on would have got an error out of the
first thing they tried.

Found by extracting the snippet from the page and compiling it under strict
with noUnusedLocals. That was done by hand -- nothing in CI checks the code in
the documentation, so the next example to go stale will go stale quietly.
Convert the library to TypeScript and ship the types
Every entry says "Thanks @enyo!", because that name is the commit author and
almost every commit here is mine. Thanking myself on each line is noise, and
worse, it spends the word on the wrong thing: it says nothing about who found
the problem or who wrote the fix.

disableThanks drops that clause and keeps what is worth having -- the links to
the pull request and the commit. Crediting somebody is now something you write
into the changeset, in a sentence that can say what they actually did:

  Send a single chunk for zero byte files instead of hanging. Reported and
  fixed by [@Forceu](https://github.com/Forceu).

The changelog-github option is used rather than its `template`, which reaches
the same place but is marked experimental and documented as able to change in
a patch release.

Entries already written are left alone; they are published history.
The publish of 6.2.1 succeeded on npm and then failed attaching dist.zip,
with "release not found" against v6.2.1.

Changesets only prefixes a tag with v for a single-package repository. In
@changesets/cli, buildGitTag returns `v${version}` when the workspace tool is
"root" and `${name}@${version}` otherwise, so becoming a pnpm workspace moved
the tags to dropzone@<version> without anything here saying so. This step
kept asking for v<version>, which had never been created.

It now uses the name and version the action reports, which is the tag
changesets built from the same two values.
The two stylesheets used sass for nesting, a handful of variables and one
math.div call. None of that needs a compiler: the sources are now the
flattened CSS sass was producing anyway, and sass is gone from the package.

Flattened rather than nested. Native CSS nesting only reached browsers in
2023, well above the range a library targeting es2017 and supporting
everything except Internet Explorer can assume.

Lightning CSS minifies them. It is the more thorough of the minifiers tried:
it drops a `background: #999` fallback that no browser in range needs,
shortens `transition: opacity .3s ease` to `.3s` because ease is the default,
and removes a dead `display: block` that was being overridden on the very
next line -- which is in the scss too, and is removed at the source here.

The supported browsers are declared once, as a browserslist field in
package.json, and the build reads them with --browserslist rather than
repeating a list of versions inside a script. That range is the one the
es2017 JavaScript target implies, and it is load-bearing: given a modern
range instead, Lightning CSS rewrites every rgba() into hex-with-alpha, which
is newer syntax than this library claims to support. Checked by widening the
field and watching the output change.

The output was compared declaration by declaration against what sass
produced: 175 effective declarations before and after in dropzone.css, 33 in
basic.css, no difference once value-level equivalences are normalised.

watch-css is removed rather than ported. It existed because sass had a
--watch flag; lightningcss has none, nothing referenced the script, and a
script called watch-css that does not watch is worse than no script.

src/.gitignore is deleted with the stylesheets. It ignored *.css and *.map
next to the sources, which was harmless while they were sass -- and silently
swallowed both new files the moment .css became the source, including hiding
them from the formatter.
Drop the sass dependency and ship plain CSS
@pull pull Bot locked and limited conversation to collaborators Sep 13, 2026
@pull pull Bot added the ⤵️ pull label Sep 13, 2026
@pull
pull Bot merged commit 616054d into AKJUS:main Sep 13, 2026
1 of 4 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant